微服务系列(六) 服务熔断与服务降级

2023-11-17

一. 背景

分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。

二. 服务雪崩

在微服务之间进行服务调用是由于某一个服务故障,导致级联服务故障的现象,称为雪崩效应。雪崩效应描述的是提供方不可用,导致消费方不可用并将不可用逐渐放大的过程。

图解雪崩效应

如存在如下调用链路:
在这里插入图片描述
而此时,Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求。此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用,这一过程如下图所示
在这里插入图片描述

雪崩效应常见场景

  • 硬件故障:如服务器宕机,机房断电,光纤被挖断等。
  • 流量激增:如异常流量,重试加大流量等。
  • 缓存穿透:一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。
  • 程序BUG:如程序逻辑导致内存泄漏,JVM长时间FullGC等。 同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。

雪崩效应应对策略

针对造成雪崩效应的不同场景,可以使用不同的应对策略,没有一种通用所有场景的策略,参考如下:

  • 硬件故障:多机房容灾、异地多活等。
  • 流量激增:服务自动扩容、流量控制(限流、关闭重试)等。
  • 缓存穿透:缓存预加载、缓存异步加载等。
  • 程序BUG:修改程序bug、及时释放资源等。
  • 同步等待:资源隔离、MQ解耦、不可用服务调用快速失败等。资源隔离通常指不同服务调用采用不同的线程池;不可用服务调用快速失败一般通过熔断器模式结合超时机制实现。

综上所述,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们的服务应当具有自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应。本文将重点介绍使用Hystrix解决同步等待的雪崩问题。

三. Histrix 使用

在这里插入图片描述
In a distributed environment, inevitably some of the many service dependencies will fail. Hystrix is a library that helps you control the interactions between these distributed services by adding latency tolerance and fault tolerance logic. Hystrix does this by isolating points of access between the services, stopping cascading failures across them, and providing fallback options, all of which improve your system’s overall resiliency.      –摘自官方

译: 在分布式环境中,许多服务依赖项不可避免地会失败。Hystrix是一个库,它通过添加延迟容忍和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止它们之间的级联故障以及提供后备选项来实现这一点,所有这些都可以提高系统的整体弹性。

1. Histrix设计与实现

Hystrix [hɪst’rɪks],中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。本文所说的Hystrix是Netflix开源的一款容错框架,同样具有自我保护能力,为了实现容错和自我保护,下面我们看看Hystrix如何设计和实现的。

Hystrix设计目标
  • 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
  • 阻止故障的连锁反应
  • 快速失败并迅速恢复
  • 回退并优雅降级
  • 提供近实时的监控与告警
Hystrix遵循的设计原则
  • 防止任何单独的依赖耗尽资源(线程)
  • 过载立即切断并快速失败,防止排队
  • 尽可能提供回退以保护用户免受故障
  • 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
  • 通过近实时的指标,监控和告警,确保故障被及时发现
  • 通过动态修改配置属性,确保故障及时恢复
  • 防止整个依赖客户端执行失败,而不仅仅是网络通信
Hystrix如何实现这些设计目标?
  • 使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或HystrixObservableCommand对象中,并将该对象放在单独的线程中执行;
    每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)。
  • 记录请求成功,失败,超时和线程拒绝。
  • 服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求。
  • 请求失败,被拒绝,超时或熔断时执行降级逻辑。
  • 近实时地监控指标和配置的修改。

2. 服务熔断和服务降级

服务熔断

“熔断器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段。
服务熔断图示:
在这里插入图片描述

服务降级

服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此环节服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的相应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。
通俗: 关闭系统中边缘服务 保证系统核心服务的正常运行 称之为服务降级
在这里插入图片描述

服务熔断与服务降级对比
共同点
  • 目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
  • 最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
  • 粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);
  • 自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段。
异同点
  • 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
  • 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)。
总结

熔断必会触发降级,所以熔断也是降级一种,区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理。

3. 使用Histrix实现服务熔断

服务熔断的实现思路
  • 引入hystrix依赖,并开启熔断器(断路器)
  • 模拟降级方法
  • 进行调用测试
项目中引入hystrix依赖
<!--引入hystrix-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
开启断路器

在启动类上加入注解
@EnableCircuitBreaker //启用断路器
注意: 这里其实也可以使用 spring cloud应用中的@SpringCloudApplication注解,因为它已经自带了这些注解,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {

}

加入注解


@SpringBootApplication
@EnableCircuitBreaker  //用来开启断路器
public class Products9998Application {
    public static void main(String[] args) {
        SpringApplication.run(Products9998Application.class, args);
    }
}
使用HystrixCommand注解实现断路

//服务熔断
@GetMapping("/product/break")
@HystrixCommand(fallbackMethod = "testBreakFall" )
public String testBreak(int id){
  log.info("接收的商品id为: "+ id);
  if(id<=0){
    throw new RuntimeException("数据不合法!!!");
  }
  return "当前接收商品id: "+id;
}

public String testBreakFall(int id){
  return "当前数据不合法: "+id;
}

在这里插入图片描述

访问测试
  • 正常参数访问
  • 错误参数访问
    在这里插入图片描述
    在这里插入图片描述
总结

从上面演示过程中会发现如果触发一定条件断路器会自动打开,过了一点时间正常之后又会关闭。那么断路器打开条件是什么呢?

断路器打开条件

A service failure in the lower level of services can cause cascading failure all the way up to the user. When calls to a particular service exceed circuitBreaker.requestVolumeThreshold (default: 20 requests) and the failure percentage is greater than circuitBreaker.errorThresholdPercentage (default: >50%) in a rolling window defined by metrics.rollingStats.timeInMilliseconds (default: 10 seconds), the circuit opens and the call is not made. In cases of error and an open circuit, a fallback can be provided by the developer.

[摘自官方]

原文翻译之后,总结打开关闭的条件:

  • 当满足一定的阀值的时候(默认10秒内超过20个请求次数)
  • 当失败率达到一定的时候(默认10秒内超过50%的请求失败)
  • 到达以上阀值,断路器将会开启
  • 当开启的时候,所有请求都不会进行转发
  • 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。重复4和5。
    在这里插入图片描述
默认的服务FallBack处理方法

如果为每一个服务方法开发一个降级,对于我们来说,可能会出现大量的代码的冗余,不利于维护,这个时候就需要加入默认服务降级处理方法。


package com.dp.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
@DefaultProperties(defaultFallback = "testBreakFall2")  //类下全局生效
public class GoodController {

    @GetMapping("/good/break")
    @HystrixCommand(fallbackMethod = "testBreakFall2") //特殊定制改接口的服务熔断方法
    public String testBreak(int id) {
        log.info("接收的商品id为: "+ id);
        if(id<=0){
            throw new RuntimeException("数据不合法!!!");
        }
        return "当前接收商品id: "+id;
    }

    @GetMapping("/goodB/break")
    @HystrixCommand  //这里不配置服务熔断方法,使用默认的处理方法
    public String testBreak2(int id) {
        log.info("接收的商品id为: "+ id);
        if(id<=0){
            throw new RuntimeException("数据不合法!!!");
        }
        return "当前接收商品id: "+id;
    }
	
	//特殊定制的熔断处理方法
    public String testBreakFall2(@RequestParam("id") int id){
        return "当前数据不合法: "+id;
    }
	
	//默认的服务熔断全局处理方法
    public String testBreakFall2(){
        return "当前数据不合法;
    }
}

测试特殊定制的服务熔断处理方法
在这里插入图片描述
测试默认的全局的服务熔断处理方法
在这里插入图片描述
可以看到一个返回了 id,一个没有返回 id。

注意:因为默认的全局服务熔断处理方法是作为一个通用方法的,不能保证参数列表中的所有参数都一样,所以必须为无参方法,否则会报错。

4. Feign 整合 Hystrix 实现服务降级

引入了feign之后,因为feign默认集成了Hystrix,所以无法像之前那样通过 @HystrixCommand注解绑定fallback方法一样实现服务降级。
feign提供了一种新方法:只需要为fegin客户端定义的接口编写一个实现类,那么这个实现类里每一个对应的重写方法,就是在feign远程调用该接口时,失败后,具体使用的降级方法。

开启 openfeign 支持服务降级
feign.hystrix.enabled=true #开启openfeign支持降级

yml文件配置如下:

server:
  port: 9998

spring:
  application:
    name: Product9998Application

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

feign:
  hystrix:
    enabled: true  #开启openfeign支持降级
在 feign 客户端中加入 fallback 映射
package com.dp.feignclient;

import com.dp.fallbackclient.FallBackClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "Product9998Application", fallback = FallBackClient.class)
public interface ProductFeign {

    @GetMapping("/product/break")
    String testBreak(@RequestParam("id") int id);
}

为feign客户端接口编写实现类FeignFallback
package com.dp.fallbackclient;

import com.dp.feignclient.ProductFeign;
import org.springframework.stereotype.Component;

@Component
public class FallBackClient implements ProductFeign {
	
	@Override
    public String testBreak(int id) {
        return "我是product模块的服务降级";
    }
}

注意:在服务调用的feign客户端中,通过@FeignClient注解里的fallback属性来绑定其对应降级方法的实现类。

业务层代码

package com.dp.controller;

import com.dp.feignclient.ProductFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class OrderController {
    @Autowired
    ProductFeign productFeign;

    @GetMapping("/get/product")
    public String getProduct(int id) {
        String result = productFeign.testBreak(id);
        return result;
    }
}

结果
在这里插入图片描述
在这里插入图片描述
注意:如果服务端降级和客户端降级同时开启,要求服务端降级方法的返回值必须与客户端方法降级的返回值一致!!!

5. Hystrix Dashboard 断路器监控

Hystrix 还提供了 准实时的调用监控(Hystrix Dashboard),Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求,多少成功,多少失败等。
Netflix 通过 hystrix-metrics-event-stream 项目实现了对以上指标的监控。同时 Spring Cloud 也提供了对 Hystrix Dashboard 的整合,将监控的内容信息转化成可视化界面。

作用
  • 实时监控各个Hystrix commandKey的各种指标值
  • 通过 Dashboards 的实时监控来动态修改各种配置

Hystrix Dashboard的一个主要优点是它收集了关于每个HystrixCommand的一组度量。Hystrix仪表板以高效的方式显示每个断路器的运行状况。

创建 HystrixDashboard 模块

在使用 Hystrix Dashboard 时,需要以单独工程的方式运行。以下就是 Hystrix Dashboard 的使用流程。

server:
  port: 8801
spring:
  application:
    name: HystrixDashboard-8801
引入依赖

注意该依赖一般情况是配合 spring-boot-starter-acurator 同时使用,该模块主要用来完成对 服务的健康监控。在生产环境中,需要实时或定期监控服务的可用性。SpringBoot 的 actuator(健康监控)功能提供了很多监控所需的接口,可以对应用系统进行配置查看、相关功能统计等。

<!--引入hystrix dashboard 依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
入口类中开启hystrix dashboard
package com.dp;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboard8801 {

    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboard8801.class, args);
    }
}

启动

启动 Hystrix Dahsboard 模块项目,我们访问 http://localhost:8801/hystrix ,就能够看到 Hystrix Dashboard 豪猪哥 的监控页面了。
在这里插入图片描述
注意: 新版本 Hystrix 需要在主启动类中指定监控路径,如果没有此项操作,在项目启动后,Hystrix Dashboard 会报: Unable to connect to Command Metric Stream 这样一个错误。配置内容如下:

package com.dp;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableCircuitBreaker
//@SpringCloudApplication
public class Product9998Application {

    public static void main(String[] args) {
        SpringApplication.run(Product9998Application.class, args);
    }

    //在主启动类中指定监控路径
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

将 服务注册中心(8761端口)、服务提供方(9998端口)、Hystrix Dashboard(8801端口) 模块进行启动。然后通过 Hystrix Dashboard 8801 来监控服务端 9998。
在这里插入图片描述

需要在 Hystrix Dashboard 中填写 监控地址:http://localhost:9998/hystrix.stream,并完成图中四部曲:
在这里插入图片描述
开启监控,所以服务都启动 ok 的话,你会看到如下界面。到此处说明配置 OK。
在这里插入图片描述

四. Hystrix 停止维护

在这里插入图片描述

翻译:Hystrix(版本1.5.18)足够稳定,可以满足Netflix对我们现有应用的需求。同时,我们的重点已经转移到对应用程序的实时性能作出反应的更具适应性的实现,而不是预先配置的设置(例如,通过自适应并发限制)。对于像Hystrix这样的东西有意义的情况,我们打算继续在现有的应用程序中使用Hystrix,并在新的内部项目中利用诸如resilience4j这样的开放和活跃的项目。我们开始建议其他人也这样做。
Dashboard也被废弃。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

微服务系列(六) 服务熔断与服务降级 的相关文章

  • 【轮播图的实现】JS的音乐播放器

    轮播图使用的场景通常在网页首页上 在有限的空间可以通过轮播图 循环播放同一类型的图片 文字等内容 轮播图目前表现形式有 2 种 一种是常规的只出现一张图片 另一种是出现三张图片凸显一张的卡片化的 因为轮播图广泛使用 目前很多工具库 例如 s
  • Linux 搭建Web虚拟机(Apache httpd),单台机搭建多web站点

    一 基础知识 虚拟web主机 指的是在同一台服务器中运行多个web站点 其中的每一个站点实际上并不独自占用整个服务器 可以充分利用服务器的硬件资源 从而大大减低网站构建及运行成本 使用httpd可以非常方便地构建虚拟机主机服务器 只需要运行
  • 2012腾讯校园招聘笔试成都站回忆版

    腾讯的笔试题目比较基础 具体的题目记不清除了 设计到的知识点 1 c语言基础 sizeof strlen的用法 2 linux基本命令umask 3 SQL语言 4 数据结构的知识 建立二叉树 顺序表操作的复杂度 5 操作系统的知识 通过页
  • c语言scanf用法

    C语言中scanf的用法和注意事项 scanf概念 scanf是格式输入函数 功能是在屏幕上输入指定的信息 简单的来说和printf相似却不相同 scanf调用格式 scanf lt 格式化字符串 gt lt 地址表 gt 如 includ
  • C Primer Plus 第六章编程练习

    第六章 编程练习 6 1 题 目 编写一个程序 创建一个包含26个元素的数组 并在其中储存26个 小写字母 然后打印数组的所有内容 完成时间 2020 2 3 作 者 林夕
  • 【项目实战】大文件断点续传,搞起

    今天给大家分享的又是一篇实战文章 也是最近私活里遇到的 万能的互联网给了我办法 分享一下 背景 最近接到一个新的需求 需要上传2G左右的视频文件 用测试环境的OSS试了一下 上传需要十几分钟 再考虑到公司的资源问题 果断放弃该方案 一提到大
  • MJRefresh原理分析

    MJRefresh是流行的下拉刷新控件 前段时间为了修复一个BUG 读了它的源码 本文总结一下实现的原理 下拉刷新的基本原理 大部分的下拉刷新控件 都是用contentInset实现的 默认情况下 如果一个UIScrollView的左上角在
  • CNN进行非接触掌纹识别的改进过程

    1 模型和参数不变 模型 2个卷积层 1个全连接层 参数 BATCH SIZE 32 定义超参数 每次处理32张图片 EPOCHS 20 将数据集训练20轮 LR 0 01 学习率 TRAIN DIVISION 3 训练集划分占比 opti
  • 小程序上线流程

    1 配置服务器域名 小程序接口API 2 业务域名配置 首先配置小程序的业务域名 将下载txt文件放在A 域名根目录下 然后才可以配置业务域名为 A 主要应用场景为 小程序页面跳转其他小程序 3 npm run build weapp 编译
  • 【数据库复习】第二章关系数据库

    目录 一 关系数据结构及形式化定义 1 1关系 1 2关系模式 1 3关系数据库 1 4关系模型的存储结构 二 关系操作 三 关系的完整性 四 关系代数 4 1传统的集合运算 4 2专门的关系运算 4 2 1选择 selection 4 2
  • const int & a = 1;

    int a 1 报错 引用需要一个合法的内存空间 const int a 1 正确 类似于int temp 1 const int a temp
  • String时间类型转换为ZonedDateTime时间类型

    搞了一个早上 不知道怎么弄这个东西 最后发现没有必要将ZonedDateTime写的很全 可以精简的封装 public static ZonedDateTime changeShanghaiToUTC String beijingDateT
  • 【MIUI9】小米平板1MIPAD1欧版ROM历史ROM下载地址-另附挥泪典藏版V9系统

    费劲整理来的 上边是 小米平板1 MIPAD1的 ROM 下边是MI3W小米3联通版的ROM 欧版xiaomi eu系统的好处就是省电 miui MIPAD V9 2 4 0 KXFCNEK 97354839c6 4 4 zip 这个是小米
  • com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message

    报错 com mongodb MongoSocketReadTimeoutException Timeout while receiving message at com mongodb connection InternalStreamC
  • C++ list容器详解

    C list容器 list容器的基本概念 1 list的构造函数 2 list的赋值和交换 3 list的大小操作 4 list的插入和删除 5 list的数据存取 6 list的反转与排序 7 list的排序案例 list容器的基本概念
  • Vue 源码解读(12)—— patch

    当学习成为了习惯 知识也就变成了常识 感谢各位的 关注 点赞 收藏和评论 新视频和文章会第一时间在微信公众号发送 欢迎关注 李永宁lyn 文章已收录到 github 仓库 liyongning blog 欢迎 Watch 和 Star 前言
  • linux系统提示只读文件系统,无法创建文件

    可能磁盘写保护 第一步 df h 确定文件夹对应的磁盘 第二步 mount ro为只读 rw为可读可写 可以用mount命令看看ro的分区 如果发现有ro 就重新mount 如 umount dev sda1 mount dev sda1
  • 备战2022,Android中高级面试必知必会

    在过去不久的金九银十 有些小伙伴已经找到了理想的工作 当然也有很多小伙伴因为准备不充分 面试挂了 临近年关 最近有很多网友都在求大厂面试题 正好我在9月份和10月份整理和收集了 Android 中高级面试真题解析 于是就发上来分享给大家 这
  • 如何使用matlab读取excel中的表格数据

    如何使用matlab读取excel中的表格数据 设备系统 win10 操作软件 matlab2020b 1 首先打开matlab软件 点击 新建 脚本 2 在脚本中输入代码 A xlsread C Users Administrator D

随机推荐

  • [附源码]java毕业设计订单管理系统

    项目运行 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEclispe Sts都支持 项目技术 SSM mybatis Ma
  • 【操作系统】虚拟内存的最大容量和实际容量的区别(以一道例题开头)

    实际内存为什么是2GB 512MB 因为实际容量是取CPU寻址 2 32B 与内存与外存之和 2GB 512MB 的最小值 就是相当于 数学里面两个值取最小值一样
  • gdbserver配置、远程调试以及ssh配置

    引言 GDB调试主要有两种方法 1 直接在目标板上通过gdb调试程序 2 在目标板上通过gdbserver运行程序 在宿主机上通过gdb调试程序 本篇文章主要来说明一下gdbserver远程调试的方法 主要以VScode举例说明 步骤 一
  • idea下载Scala插件(详细)

    目录 1 idea下载Scala 2 点击 Restart IDE 重启IDEA即可 3 创建scala目录 4 Mark scala目录为 source root 5 在windows的电脑安装scala jdk并且配置 环境变量 6 在
  • labelImg支持中文标注的文件

    链接 https pan baidu com s 1XCuLTlKRN7gVxJdQkcKnUw 密码 iaws
  • 读者-写者问题 (操作系统-进程)

    读者 写者问题 读进程优先算法 写者优先算法 问题描述 有读者和写者两组并发进程 共享一个文件 当两个或两个以上的读进程同时访问共享数据时不会产生副作用 但若某个写进程和其他进程 读进程或写进程 同时访问共享数据时则可能导致数据不一致的错误
  • 用vue3+elementplus做的一个滚动菜单栏的组件

    目录 起因 概览 设计及解决思路 1 滚动条竖起来 2 绑定菜单 3 吸附 优化 组件全部代码 起因 在elementplus中看到了滚动条绑定了slider 但是这个感觉很不实用 在底部 而且横向滚动 最常见的应该是那种固定在左上角的带着
  • 交叉编译适配mips架构的GDB

    交叉编译GDB 交叉编译GDB 1 下载GDB源码 2 解压并创建安装目录 3 编译安装 4 可能遇到的错误解决方法 1 下载termcap 2 将上面的编译安装gdb的脚本改一下 3 对于最后的权限不够无法删除PC机上termcap h文
  • 使用UE4(UnrealEngine)创建工程

    UE4系列文章目录 文章目录 UE4系列文章目录 前言 一 步骤 1 打开UE4软件 2 新建工程 3 选择游戏类型模板 4 项目设置 运行游戏 前言 使用UE4 UnrealEngine 创建工程 我这里的ue4版本是4 27 2 一 步
  • stm32循迹小车详细制作过程(附加完全版代码)

    stm32循迹小车详细制作过程 一 材料准备 1 主控板 Stm32f103c8t6 推荐 便宜够用 2 下载器 USB转TTL串口模块 3 电源 12v锂电池组 配套充电器 推荐下图这种 方便 好接线 12v 12v 12v 4 电机驱动
  • No module named ‘dateutil‘解决

    运行程序报错 无法直接pip install dateutil 需要pip install python dateutil
  • [非线性控制理论]6_滑模控制 (sliding mode control)

    非线性控制理论 1 Lyapunov直接方法 非线性控制理论 2 不变性原理 非线性控制理论 3 基础反馈稳定控制器设计 非线性控制理论 4 反馈线性化 反步法 非线性控制理论 5 自适应控制器 Adaptive controller 非线
  • CF 935E - Fafa and Ancient Mathematics

    CF 935E Fafa and Ancient Mathematics 题目描述 定义合法数学表达式 E E E 为一个数或两个合法数学表达式中间加上一个加或减运算符 并且在外面加上一对括号 给定一个合法数学表达式 将其中加减运算符用
  • QML Image内部缓存导致的问题

    QML Image BUG BUG描述 两个界面login qml 和 modify qml 页面 内部代码大致如下 Camera id camera imageProcessing whiteBalanceMode CameraImage
  • python实现vlookup_干货一:怎么在python里面实现vlookup

    vlookup应该是excel里用的比较多的功能 我刚接触excel的时候 反正觉得这个功能非常神奇 省了很多事 但是用久了以后就发现vlookup的限制太多了 第一大痛点 只能往右边 gt 找 如果要往左边找 最笨的办法就是把要找的col
  • rpm软件包解读

    一 linux应用程序与系统命令关系 二 典型应用程序的目录结构 三 常见的软件包封装类型 RPM包管理工具 RPM软件包管理器RED HAT PACKAGE MANAGER 由Red Hat公司提出 被众多linux发行版所采用 建立统一
  • 【机器学习】Q-Learning详细介绍

    Q learning Q learning 是一种机器学习方法 它使模型能够通过采取正确的操作来迭代学习和改进 Q learning属于强化学习的算法 通过强化学习 可以训练机器学习模型来模仿动物或儿童的学习方式 好的行为会得到奖励或加强
  • 如何从几何角度上理解方程组只有一个解_线性方程组的解集及其几何意义

    由于这三者之间的等价关系 我们解决现实问题时可以自由选取其中任意一个作为模型 我个人认为 线性方程组是最 质朴 的形式 向量方程则是与几何建立了关系 这将方便我们进行更直观的推理 矩阵方程则是向量方程的一种 封装 是向量方程的一种抽象 它将
  • Hotspot 垃圾回收之ConcurrentMarkSweepThread 源码解析

    目录 一 ConcurrentGCThread 二 SurrogateLockerThread 1 make 2 loop manipulatePLL 三 ConcurrentMarkSweepThread 1 定义 2 start和构造方
  • 微服务系列(六) 服务熔断与服务降级

    一 背景 分布式系统环境下 服务间类似依赖非常常见 一个业务调用通常依赖多个基础服务 如下图 对于同步调用 当库存服务不可用时 商品服务请求线程被阻塞 当有大批量请求调用库存服务时 最终可能导致整个商品服务资源耗尽 无法继续对外提供服务 并