百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

SpringCloud之熔断器Hystrix springcloud熔断器原理

xsobi 2024-12-18 17:47 2 浏览

Hystrix 是什么

Hystrix被称为熔断器,它是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多服务之间通过远程调用实现信息交互,调用时不可避免会出现调用失败,比如超时、异常等原因导致调用失败,Hystrix能够保证在一个服务出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩),以提高分布式系统的弹性;

熔断器也有叫断路器,他们表示同一个意思,最早来源于微服务之父 MartinFowler 的论文 CircuitBreaker 一文。“熔断器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,能够及时切断故障电路,防止发生过载、发热甚至起火等严重后果。

所以当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

比如:

比如电商中的用户下订单,我们有两个服务,一个下订单服务,一个减库存服务,当用户下订单时调用下订单服务,然后下订单服务又调用减库存服务,如果减库存服务响应延迟或者没有响应,则会造成下订单服务的线程挂起等待,如果大量的用户请求下订单,或导致大量的请求堆积,引起下订单服务也不可用,如果还有另外一个服务依赖于订单服务,比如用户服务,它需要查询用户订单,那么用户服务查询订单也会引起大量的延迟和请求堆积,导致用户服务也不可用。

所以在微服务架构中,很容易造成服务故障的蔓延,引发整个微服务系统瘫痪不可用。

Spring Cloud Hystrix 实现了熔断器、线程隔离等一系列服务保护功能。该功能也是基于Netflix 的开源框架 Hystrix 实现的,该框架的目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。 (Spring Cloud Hystrix 对 Netflix Hystrix 做了一个starter)

程序BUG,数据不匹配,响应时间过长,服务不可用 等等.....都可能导致服务雪崩;

针对上面的问题,hystrix提供了 :

  • 熔断降级
  • 请求限流

服务降级是指当某个微服务响应时间过长,发生异常,或者服务不可用了,我们不能把错误信息返回回来,或者让它一直卡在那里,所以要准备一个对应的策略(一个方法),当发生这种问题时,我们直接调用这个备用的方法来快速返回一个默认的结果,让请求得到快速响应,而不是一直卡在那里;

springcloud视频观看戳~~~~

SpringCloud微服务架构实战

https://www.ixigua.com/6895923297481916939

操作步骤

在 Spring Cloud 中使用熔断器 Hystrix 是非常简单和方便的,只需要简单两步即可:

1、加依赖

<!-- spring-cloud-starter-netflix-hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2、在入口类中使用@EnableCircuitBreaker 注解或 @EnableHystrix开启断路器功能,也可以使用一个名为@SprinGCloudApplication 的注解代替主类上的三个注解;

3、在调用远程服务的方法上添加注解:

@HystrixCommand(fallbackMethod = "fallback")

hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发断路器;

修改 hystrix 的默认超时时间:

@RequestMapping("/cloud/goodsHystrix")
@HystrixCommand(fallbackMethod = "fallback",
                commandProperties={
                        @HystrixProperty(name="execution.timeout.enabled", value="true"),
                    @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="5000")
                })
public ResultObject goodsHystrix()

或者在配置文件进行配置:

ribbon.ReadTimeout=6000
ribbon.ConnectTimeout=3000
hystrix.command.default.execution.timeout.enabled=true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000

这里有个坑需要注意一下:

如果hystrix.command.default.execution.timeout.enabled为true,则会有两个执行方法超时的配置,一个就是ribbon的ReadTimeout,一个就是熔断器hystrix的timeoutInMilliseconds, 此时谁的值小谁生效;

如果hystrix.command.default.execution.timeout.enabled为false,则熔断器不进行超时熔断,而是根据ribbon的ReadTimeout抛出的异常而熔断,也就是取决于ribbon的ConnectTimeout,配置的是请求服务的超时时间,除非服务找不到,或者网络原因,这个时间才会生效;

ribbon.ReadTimeout=6000
ribbon.ConnectTimeout=3000

Hystrix的异常处理

我们在调用服务提供者时,服务提供者可能抛出异常,我们自己也可能抛异常,默认情况下方法抛了异常会自动进行服务降级,交给服务降级中的方法去处理;

当我们自己发生异常后,只需要在服务降级方法中添加一个 Throwable 类型的

参数就能够获取到抛出的异常的类型,如下:

public ResultObject fallback(Throwable throwable) {
    System.out.println(throwable.getMessage());
    return new ResultObject(Constant.ONE,"服务降级");
}

当然远程服务发生了异常也可以获取到异常信息;

如果远程服务有一个异常抛出后我们不希望进入到服务降级方法中去处理,而是直接将异常抛给用户,那么我们可以在@HystrixCommand 注解中添加忽略异常,

如下:

@HystrixCommand(fallbackMethod = "fallback", ignoreExceptions=Throwable.class,

降级是作用?

1、可以监听你的请求有没有超时;(默认是1秒,时间可以改)

2、异常或报错了可以快速让请求返回,不会一直等待;(避免线程累积)

3、当的系统马上迎来大量的并发(双十一秒杀这种或者促销活动) 此时如果系统承载不了这么大的并发时,可以考虑先关闭一些不重要的微服务(在降级方法中返回一个比较友好的信息),把资源让给核心微服务,待高峰流量过去,再开启回来。

Hystrix限流

限流有很多方案:

1、Nginx

2、Redis + Lua

3、Sentinel

4、基于限流算法自己实现(令牌桶、漏桶算法)

hystrix限流就是限制你某个微服务的使用量(可用线程数、信号量)

hystrix通过线程池的方式来管理微服务的调用,它默认是一个线程池(大小10个) 管理你的所有微服务,你可以给某个微服务开辟新的线程池:

@RequestMapping("/cloud/goodsHystrix2")
@HystrixCommand(fallbackMethod = "fallback",
                threadPoolKey = "goods",
                threadPoolProperties = {@HystrixProperty(name = "coreSize", value = "2"),
                @HystrixProperty(name = "maxQueueSize", value = "1")})
public ResultObject goodsHystrix2() throws InterruptedException {

threadPoolKey 是线程池唯一标识, hystrix 会使用该标识来计数,看线程占用是否超过了, 超过了就会直接降级该次调用;

这里coreSize给他值为2 那么假设你这个方法调用时间是1s执行完, 那么在1s内如果有超过2个请求进来的话,剩下的请求则全部降级;

其中maxQueueSize是一个线程队列,里面只能放一个请求线程,本来线程数有2个,队列里面允许放一个,那么总共只能有3个请求线程执行,如果超过了就会限流;

feign整合hystrix

feign 默认是支持hystrix的, 但是在Spring cloud Dalston 版本之后就默认关闭了, 因为业务需求不一定要使用;

所以现在要使用首先得打开他,在yml文件加上如下配置:

feign.hystrix.enabled=true

加上配置之后降级方法怎么写呢?

@FeignClient(value="34-SPRINGCLOUD-SERVICE-GOODS", fallback = GoodsRemoteClientFallBack.class)
public interface GoodsRemoteClient {
    /**
     * 声明一个feign的接口,它的实现是服务提供者的controller实现
     *
     * @return
     */
    @RequestMapping("/service/goods")
    public ResultObject goods();
}

在feign客户端的注解上 有个属性叫fallback 然后指向一个类

GoodsRemoteClientFallBack类:
@Component
public class GoodsRemoteClientFallBack implements GoodsRemoteClient {
    @Override
    public ResultObject goods() {
        return new ResultObject(Constant.ONE,"feign服务调用降级");
    }
}

如此方法降级便可以了;

当然如果需要拿到具体的服务错误信息,那么可以这样:

客户端指定一个fallbackFactory即可;

@FeignClient(value="34-SPRINGCLOUD-SERVICE-GOODS", fallbackFactory = GoodsRemoteClientFallBackFactory.class)
public interface GoodsRemoteClient {
    /**
     * 声明一个feign的接口,它的实现是服务提供者的controller实现
     *
     * @return
     */
    @RequestMapping("/service/goods")
    public ResultObject goods();
}
@Component
public class GoodsRemoteClientFallBackFactory implements FallbackFactory<GoodsRemoteClient> {
    @Override
    public GoodsRemoteClient create(Throwable throwable) {
        return new GoodsRemoteClient() {
            @Override
            public ResultObject goods() {
                String message = throwable.getMessage();
                System.out.println("feign远程调用异常:" + message);
                return new ResultObject();
            }
        };
    }
}

这个message 就是错误信息,至此,就完成了feign与hystrix的整合;

Spring Cloud Feign超时时间设置

Feign调用服务的默认时长是1秒钟,也就是如果超过1秒没连接上或者超过1秒没响应,那么会相应的报错。而实际情况是因为业务的不同可能出现超出1秒的情况,这时我们需要调整超时时间。

Feign 的负载均衡底层用的就是 Ribbon在application.properties中添加如下配置,超过5秒没连接上报连接超时,如果超过5秒没有响应,报请求超时;

# 参考RibbonClientConfiguration

# 请求连接的超时时间 默认的时间为 1 秒

ribbon.ConnectTimeout=5000

# 请求处理的超时时间

ribbon.ReadTimeout=5000

ribbon还有MaxAutoRetries对当前实例的重试次数,

MaxAutoRetriesNextServer对切换实例的重试次数,

如果ribbon的ReadTimeout超时,或者ConnectTimeout连接超时,会进行重试操作

由于ribbon的重试机制,通常熔断hystrix的超时时间需要配置的比ReadTimeou长,ReadTimeout比ConnectTimeout长,否则还未重试,就熔断了;

为了确保重试机制的正常运作,理论上(以实际情况为准)建议hystrix的超时时间为:(1 + MaxAutoRetries + MaxAutoRetriesNextServer) * ReadTimeout

hystrix相关配置:

Execution相关的属性的配置

  • hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore(信号量)
  • hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000ms
  • hystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用true
  • hystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认true
  • hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。semaphore应该占整个容器(tomcat)的线程池的一小部分。 Fallback相关的属性 这些参数可以应用于Hystrix的THREAD和SEMAPHORE策略;
  • hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequest如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。默认10
  • hystrix.command.default.fallback.enabled 当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true

Circuit Breaker相关的属性

  • hystrix.command.default.circuitBreaker.enabled 用来跟踪circuit的健康性,如果未达标则让request短路。默认true
  • hystrix.command.default.circuitBreaker.requestVolumeThreshold 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求, 即使19个请求都失败,也不会触发circuit break。默认20
  • hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。 默认5000
  • hystrix.command.default.circuitBreaker.errorThresholdPercentage错误比率阀值,如果错误率>=该 值,circuit会被打开,并短路所有请求触发fallback。默认50
  • hystrix.command.default.circuitBreaker.forceOpen 强制打开熔断器,如果打开这个开关,那么拒绝所 有request,默认false
  • hystrix.command.default.circuitBreaker.forceClosed 强制关闭熔断器 如果这个开关打开,circuit将 一直关闭且忽略circuitBreaker.errorThresholdPercentage

Metrics相关参数

  • hystrix.command.default.metrics.rollingStats.timeInMilliseconds 设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒, 则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000
  • hystrix.command.default.metrics.rollingStats.numBuckets 设置一个rolling window被划分的数 量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10
  • hystrix.command.default.metrics.rollingPercentile.enabled 执行时是否enable指标的计算和跟踪, 默认true
  • hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds 设置rolling percentile window的时间,默认60000
  • hystrix.command.default.metrics.rollingPercentile.numBuckets 设置rolling percentile window的numberBuckets。逻辑同上。默认6
  • hystrix.command.default.metrics.rollingPercentile.bucketSize 如果bucket size=100,window =10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序 的开销。默认100
  • hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 记录health 快照(用 来统计成功和错误绿)的间隔,默认500ms

Request Context 相关参数

  • hystrix.command.default.requestCache.enabled 默认true,需要重载getCacheKey(),返回null时不 缓存hystrix.command.default.requestLog.enabled 记录日志到HystrixRequestLog,默认true

Collapser Properties 相关参数

  • hystrix.collapser.default.maxRequestsInBatch 单次批处理的最大请求数,达到该数量触发批处理,默认 Integer.MAX_VALU
  • hystrix.collapser.default.timerDelayInMilliseconds 触发批处理的延迟,也可以为创建批处理的时间 +该值,默认10
  • hystrix.collapser.default.requestCache.enabled 是否对HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默认true

ThreadPool 相关参数

  • 线程数默认值10适用于大部分情况(有时可以设置得更小),如果需要设置得更大,那有个基本得公式可以 follow: requests per second at peak when healthy × 99th percentile latency in seconds + some breathing room 每秒最大支撑的请求数 (99%平均响应时间 + 缓存值) 比如:每秒能处理1000个请求,99%的请求响应时间是60ms,那么公式是: 1000 (0.060+0.012)基本得原则时保持线程池尽可能小,他主要是为了释放压力,防止资源被阻塞。 当一切都是正常的时候,线程池一般仅会有1到2个线程激活来提供服务hystrix.threadpool.default.coreSize 并发执行的最大线程数,默认10
  • hystrix.threadpool.default.maxQueueSize BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。
  • hystrix.threadpool.default.queueSizeRejectionThreshold 即使maxQueueSize没有达到,达到 queueSizeRejectionThreshold该值后,请求也会被拒绝。因为maxQueueSize不能被动态修改,这个参数将允 许我们动态设置该值。if maxQueueSize == 1,该字段将不起作用 hystrix.threadpool.default.keepAliveTimeMinutes 如果corePoolSize和maxPoolSize设成一样(默认 实现)该设置无效。如果通过plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定义 实现,该设置才有用,默认1.
  • hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds 线程池统计指标的时间,默 认10000
  • hystrix.threadpool.default.metrics.rollingStats.numBuckets 将rolling window划分为n个 buckets,默认10;

相关推荐

好用的云函数!后端低代码接口开发,零基础编写API接口

前言在开发项目过程中,经常需要用到API接口,实现对数据库的CURD等操作。不管你是专业的PHP开发工程师,还是客户端开发工程师,或者是不懂编程但懂得数据库SQL查询,又或者是完全不太懂技术的人,通过...

快速上手:Windows 平台上 cURL 命令的使用方法

在工作流程中,为了快速验证API接口有效性,团队成员经常转向直接执行cURL命令的方法。这种做法不仅节省时间,而且促进了团队效率的提升。对于使用Windows系统的用户来说,这里有一套详细...

使用 Golang net/http 包:基础入门与实战

简介Go的net/http包是构建HTTP服务的核心库,功能强大且易于使用。它提供了基本的HTTP客户端和服务端支持,可以快速构建RESTAPI、Web应用等服务。本文将介绍ne...

#小白接口# 使用云函数,人人都能编写和发布自己的API接口

你只需编写简单的云函数,就可以实现自己的业务逻辑,发布后就可以生成自己的接口给客户端调用。果创云支持对云函数进行在线接口编程,进入开放平台我的接口-在线接口编程,设计一个新接口,设计和配置好接口参...

极度精神分裂:我家没有墙面开关,但我虚拟出来了一系列开关

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:iN在之前和大家说过,在iN的家里是没有墙面开关的。...

window使用curl命令的注意事项 curl命令用法

cmd-使用curl命令的注意点前言最近在cmd中使用curl命令来测试restapi,发现有不少问题,这里记录一下。在cmd中使用curl命令的注意事项json不能由单引号包括起来json...

Linux 系统curl命令使用详解 linuxctrl

curl是一个强大的命令行工具,用于在Linux系统中进行数据传输。它支持多种协议,包括HTTP、HTTPS、FTP等,用于下载或上传数据,执行Web请求等。curl命令的常见用法和解...

Tornado 入门:初学者指南 tornados

Tornado是一个功能强大的PythonWeb框架和异步网络库。它最初是为了处理实时Web服务中的数千个同时连接而开发的。它独特的Web服务器和框架功能组合使其成为开发高性能Web...

PHP Curl的简单使用 php curl formdata

本文写给刚入PHP坑不久的新手们,作为工具文档,方便用时查阅。CURL是一个非常强大的开源库,它支持很多种协议,例如,HTTP、HTTPS、FTP、TELENT等。日常开发中,我们经常会需要用到cur...

Rust 服务器、服务和应用程序:7 Rust 中的服务器端 Web 应用简介

本章涵盖使用Actix提供静态网页...

我给 Apache 顶级项目提了个 Bug apache顶级项目有哪些

这篇文章记录了给Apache顶级项目-分库分表中间件ShardingSphere提交Bug的历程。说实话,这是一次比较曲折的Bug跟踪之旅。10月28日,我们在GitHub上提...

linux文件下载、服务器交互(curl)

基础环境curl命令描述...

curl简单使用 curl sh

1.curl--help#查看关键字2.curl-A“(添加user-agent<name>SendUser-Agent<name>toserver)”...

常用linux命令:curl 常用linux命令大全

//获取网页内容//不加任何选项使用curl时,默认会发送GET请求来获取内容到标准输出$curlhttp://www.baidu.com//输出<!DOCTYPEh...

三十七,Web渗透提高班之hack the box在线靶场注册及入门知识

一.注册hacktheboxHackTheBox是一个在线平台,允许测试您的渗透技能和代码,并与其他类似兴趣的成员交流想法和方法。它包含一些不断更新的挑战,并且模拟真实场景,其风格更倾向于CT...