1. Feign+Hystrix实现RPC调用保护
在Spring Cloud微服务架构下,RPC保护可以通过Hystrix开源组件来实现,并且Spring Cloud对Hystrix组件进行了集成,使用起来非常方便。
Hystrix翻译过来是豪猪,由于豪猪身上长满了刺,因此能保护自己不受天敌的伤害,代表了一种防御机制。Hystrix开源框架是Netflix开源的一个延迟和容错的组件,主要用于在远程Provider服务异常时对消费端的RPC进行保护。
有关Hystrix的详细资料,可参考其官方网站:https://github.com/Netflix/Hystrix
使用步骤
- 引入依赖
<!--引入Spring Cloud Hystrix依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
- 在Spring Cloud架构中,Hystrix是和Feign组合起来使用的,所以需要在应用的属性配置文件中开启Feign对Hystrix的支持:
在Spring Cloud架构中,Hystrix是和Feign组合起来使用的,所以需要在应用的属性配置文件中开启Feign对Hystrix的支持: feign: enabled: true #开启Hystrix对Feign的支持
在启动类上添加@EnableHystrix或者@EnableCircuitBreaker。注意,@EnableHystrix中包含了@EnableCircuitBreaker。
Spring Cloud Hystrix的RPC保护功能包括失败回退、熔断、重试、舱壁隔离等。
2. Spring Cloud Hystrix失败回退
1.什么是失败回退呢?当目标Provider实例发生故障时,RPC的失败回退会产生作用,返回一个后备的结果。
2.一个失败回退的演示如图所示,有A、B、C、D四个Provider实例,A-Provider和B-Provider对D-Provider发起RPC远程调用,但是D-Provider发生了故障,在A、B收到失败回退保护的情况下,最终会拿到失败回退提供的后备结果(或者Fallback回退结果)。
3.如何设置RPC调用的回退逻辑呢?有两种方式:(1)定义和使用一个Fallback回退处理类。(2)定义和使用一个FallbackFactory回退处理工厂类。
4.在进行失败回退时,使用第一种方式的回退类和使用第二种方式的回退工厂类有什么区别呢?答案是:在使用第一种方式的回退类时,远程调用RPC过程中所引发的异常已经被回退逻辑彻底地屏蔽掉了。应用程序不太方便干预,也看不到RPC过程中的具体异常,尽管这些异常对于问题的排除非常有帮助。在使用第二种方式的回退工厂类时,应用程序可以通过Java代码对RPC异常进行拦截和处理,包括进行日志输出。
3. Spring Cloud Hystrix熔断器
- 在物理学上,熔断器本身是一个开关装置,用在电路上保护线路过载,当线路中有电器发生短路时,熔断器能够及时切断故障,防止发生过载、发热甚至起火等严重后果。
- 分布式架构中的熔断器主要用于RPC接口上,为接口安装上“保险丝”,以防止RPC接口出现拥塞时导致系统压力过大而引起的系统瘫痪,当RPC接口流量过大或者目标Provider出现异常时,熔断器及时切断故障可以起到自我保护的作用。
- 为什么说熔断器非常重要呢?如果没有过载保护,在分布式系统中,当被调用的远程服务无法使用时,就会导致请求的资源阻塞在远程服务器上而耗尽。很多时候刚开始可能只是出现了局部小规模的故障,然而由于种种原因,故障影响范围越来越大,最终导致全局性的后果。
- 熔断器具体的工作机制为:统计最近RPC调用发生错误的次数,然后根据统计值中的失败比例等信息来决定是否允许后面的RPC调用继续或者快速地失败回退。
- 熔断器的3种状态如下:
- 关闭(closed):熔断器关闭状态,这也是熔断器的初始状态,此状态下RPC调用正常放行。
- 开启(open):失败比例到一定的阈值之后,熔断器进入开启状态,此状态下RPC将会快速失败,然后执行失败回退逻辑。
- 半开启(half-open):在打开一定时间之后(睡眠窗口结束),熔断器进入半开启状态,小流量尝试进行RPC调用放行。如果尝试成功,熔断器就变为关闭状态,RPC调用正常;如果尝试失败,熔断器就变为开启状态,RPC调用快速失败。
熔断器状态之间的相互转换关系如图所示。
在半开启状态下,允许进行一次RPC调用的尝试,如果实际调用成功,熔断器就会复位到关闭状态,回归正常的模式;但是如果这次RPC调用的尝试失败,熔断器就会返回到开启状态,一直等待到下次半开启状态。
Spring Cloud Hystrix中的熔断器默认是开启的,但是可以通过配置熔断器的参数进行定制。下面是demo-provider微服务中熔断器示例的相关配置:
hystrix: ... command: default: ... circuitBreaker: #熔断器相关配置 enabled: true #是否使用熔断器,默认为true requestVolumeThreshold: 20 #窗口时间内的最小请求数 sleepWindowInMilliseconds: 5000 #打开后允许一次尝试的睡眠时间,默认配置为5秒 errorThresholdPercentage: 50 #窗口时间内熔断器开启的错误比例,默认配置为50 metrics: rollingStats: timeInMilliseconds: 10000 #滑动窗口时间 numBuckets: 10 #滑动窗口的时间桶数
- 以上用到的Hystrix熔断器相关参数分为两类:熔断器相关参数和滑动窗口相关参数。
- 对示例中用到的熔断器的相关参数大致介绍如下:
- hystrix.command.default.circuitBreaker.enabled:该配置用来确定熔断器是否用于跟踪RPC请求的运行状态,或者说用于配置是否启用熔断器,默认值为true。
- hystrix.command.default.circuitBreaker.requestVolumeThreshold:该配置用于设置熔断器触发熔断的最少请求次数。如果设置为20,那么当一个滑动窗口时间内(比如10秒)收到19个请求时,即使19个请求都失败,熔断器也不会打开变成open状态,默认值为20。
- hystrix.command.default.circuitBreaker.errorThresholdPercentage:该配置用于设置错误率阈值,在滑动窗口时间内,当错误率超过此值时,熔断器进入open状态,所有请求都会触发失败回退(fallback),错误率阈值百分比的默认值为50。
- hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds:该配置用于设置熔断器的睡眠窗口,具体指的是确定熔断器打开之后多长时间才允许一次请求尝试执行,默认值为5 000毫秒,表示当熔断器打开后,5 000毫秒内会拒绝所有请求,5 000毫秒后熔断器才会进行入half-open状态。
- hystrix.command.default.circuitBreaker.forceOpen:如果配置为true,熔断器就会被强制打开,所有请求将触发失败回退(Fallback),默认值为false。
11.熔断器的状态转换与Hystrix的滑动窗口的健康统计值(比如失败比例)相关。接下来对示例中使用到的Hystrix健康统计相关配置大致介绍如下:
- hystrix.command.default.metrics.rollingStats.timeInMilliseconds:设置统计滑动窗口的持续时间(以毫秒为单位),默认值为10 000毫秒。熔断器的打开会根据一个滑动窗口的统计值来计算,若滑动窗口时间内的错误率超过阈值,则熔断器进入开启状态。滑动窗口将被进一步细分为时间桶(Bucket),滑动窗口的统计值等于窗口内所有时间桶的统计信息的累加,每个时间桶的统计信息包含请求成功(Success)、失败(Failure)、超时(Timeout)、被拒(Rejection)的次数。
- hystrix.command.default.metrics.rollingStats.numBuckets:设置一个滑动窗口被划分的时间桶数量,默认值为10。若滑动窗口的持续时间为10 000毫秒,并且一个滑动窗口被划为10个时间桶,则一个时间桶的时间为1秒。所设置的numBuckets(时间桶数量)和timeInMilliseconds(滑动窗口时长)的值有一定关系,必须符合timeInMilliseconds%numberBuckets==0的规则,否则会抛出异常,例如70 000(滑动窗口70 000毫秒)%700(桶数)==0是可以的,但是70000(滑动窗口70 000毫秒)%600(桶数)==400将抛出异常。
以上有关Hystrix熔断器的配置选项使用的是hystrix.command.default前缀,这些默认配置项将对项目中所有Feign RPC接口生效,除非某个Feign RPC接口进行单独配置。如果需要对某个Feign RPC调用进行特殊的配置,配置项前缀的格式如下:
hystrix.command.类名#方法名(参数类型列表)
下面来看一个对单个接口进行特殊配置的例子,以对UserClient类中的Feign RPC接口/detail/v1进行特殊配置为例。
hystrix: ... command: UserClient#detail(Long): #格式为:类名#方法名(参数类型列表) ... circuitBreaker: #熔断器相关配置 enabled: true #是否使用熔断器,默认为true requestVolumeThreshold: 20 #至少有20个请求,熔断器才会达到熔断触发的次数阈值 sleepWindowInMilliseconds: 5000 #打开后允许一次尝试的睡眠时间,默认配置为5秒 errorThresholdPercentage: 50 #窗口时间内熔断器开启的错误比例,默认配置为50 metrics: rollingPercentile: timeInMilliseconds: 60000 #滑动窗口时间 numBuckets: 600 #滑动窗口的时间桶数 bucketSize: 200 #时间桶内的统计次数