8.8 Hystrix服务熔断
-
熔断机制是对应雪崩效应的一种微服务链路保护机制。
-
当扇出链路的某个微服务不可用或者响应时间太长时,为了保护系统的整体可用性,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。这种熔断状态不是永久的,在经历了一定的时间后,熔断器会再次检测该微服务是否恢复正常,若服务恢复正常则恢复其调用链路。
-
熔断状态:在熔断机制中涉及了三种熔断状态:
- 熔断关闭状态(Closed):当服务访问正常时,熔断器处于关闭状态,服务调用方可以正常地对服务进行调用。
- 熔断开启状态(Open):默认情况下,在固定时间内接口调用出错比率达到一个阈值(例如 50%),熔断器会进入熔断开启状态。进入熔断状态后,后续对该服务的调用都会被切断,熔断器会执行本地的降级(FallBack)方法。
- 半熔断状态(Half-Open): 在熔断开启一段时间之后,熔断器会进入半熔断状态。在半熔断状态下,熔断器会尝试恢复服务调用方对服务的调用,允许部分请求调用该服务,并监控其调用成功率。如果成功率达到预期,则说明服务已恢复正常,熔断器进入关闭状态;如果成功率仍旧很低,则重新进入熔断开启状态。
-
Hystrix实现熔断机制:在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
-
Hystrix 实现服务熔断的步骤如下:
- 当服务的调用出错率达到或超过 Hystix 规定的比率(默认为 50%)后,熔断器进入熔断开启状态。
- 熔断器进入熔断开启状态后,Hystrix 会启动一个休眠时间窗,在这个时间窗内,该服务的降级逻辑会临时充当业务主逻辑,而原来的业务主逻辑不可用。
- 当有请求再次调用该服务时,会直接调用降级逻辑快速地返回失败响应,以避免系统雪崩。
- 当休眠时间窗到期后,Hystrix 会进入半熔断转态,允许部分请求对服务原来的主业务逻辑进行调用,并监控其调用成功率。
- 如果调用成功率达到预期,则说明服务已恢复正常,Hystrix 进入熔断关闭状态,服务原来的主业务逻辑恢复;否则 Hystrix 重新进入熔断开启状态,休眠时间窗口重新计时,继续重复第 2 到第 5 步。
-
验证下 Hystrix 是如何实现熔断机制的,在microservice-cloud-provider-dept-hystrix-8004 中的 DeptService 接口中添加一个 deptCircuitBreaker() 方法,代码如下。
package com.example.service;
/**
* @author CNCLUKZK
* @create 2022/9/20-13:24
*/
public interface DeptService {
// hystrix 熔断器示例 ok
String dept_200(Integer id);
//hystrix 熔断器超时案例
String dept_timeout_500(Integer id);
// Hystrix 熔断机制案例
String deptCircuitBreaker(Integer num);
}
- 在 DeptService接口的实现类 DeptServiceImpl 添加 deptCircuitBreaker() 的方法实现及其回退方法,代码如下。
package com.example.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.apache.commons.codec.digest.Md5Crypt;
import org.springframework.cloud.commons.util.IdUtils;
import org.springframework.stereotype.Service;
import sun.security.provider.MD5;
import sun.security.rsa.RSASignature;
import java.util.concurrent.TimeUnit;
/**
* @author CNCLUKZK
* @create 2022/9/20-13:26
*/
@Service("deptService")
public class DeptServiceImpl implements DeptService{
@Override
public String dept_200(Integer id) {
return "服务端当前线程:"+Thread.currentThread().getName()+"请求处理成功200。ID+"+id;
}
//一旦该方法失败并抛出了异常信息后,会自动调用 @HystrixCommand 注解标注的 fallbackMethod 指定的方法
@HystrixCommand(fallbackMethod = "dept_timeout_handler",
规定 5 秒钟以内就不报错,正常运行,超过 5 秒就报错,调用指定的方法
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")})
@Override
public String dept_timeout_500(Integer id) {
try {
//Thread.sleep(6000);
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "服务端当前线程:"+Thread.currentThread().getName()+"请求超时500。ID+"+id;
}
//Hystrix 熔断机制案例
@HystrixCommand(fallbackMethod = "circuitBreakerFallbackMethod",
规定 5 秒钟以内就不报错,正常运行,超过 5 秒就报错,调用指定的方法
commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //是否开启熔断器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //统计时间窗内请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //休眠时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),//在统计时间窗口期以内,请求失败率达到 50% 时进入熔断状态
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "1000"),//统计时间窗
})
@Override
public String deptCircuitBreaker(Integer num) {
if(String.valueOf(num).length() < 6){
//当传入的 num 位数< 6时,抛出异常,调用降级方法
throw new RuntimeException("服务端提示,num位数不能少于6位!");
}
String apr1 = Md5Crypt.apr1Crypt(String.valueOf(num));
return Thread.currentThread().getName()+"加密前参数为:"+num+" 加密后值为:"+apr1;
}
// 当服务出现故障后,调用该方法给出友好提示
public String dept_timeout_handler(Integer id){
return "服务端因当前请求超时,服务降级,返回提示信息!当前线程:"+Thread.currentThread().getName()+"请求超时500。ID+"+id;
}
//熔断案例降级方法
public String circuitBreakerFallbackMethod(Integer num) {
return "服务端提示,num位数不能少于6位!请稍后重试。num:"+num;
}
}
- 在以上代码中,共涉及到了 4 个与 Hystrix 熔断机制相关的重要参数,这 4 个参数的含义如下表。
参数 | 描述 |
---|---|
metrics.rollingStats.timeInMilliseconds | 统计时间窗。 |
circuitBreaker.sleepWindowInMilliseconds | 休眠时间窗,熔断开启状态持续一段时间后,熔断器会自动进入半熔断状态,这段时间就被称为休眠窗口期。 |
circuitBreaker.requestVolumeThreshold | 请求总数阀值。 在统计时间窗内,请求总数必须到达一定的数量级,Hystrix 才可能会将熔断器打开进入熔断开启转态,而这个请求数量级就是 请求总数阀值。Hystrix 请求总数阈值默认为 20,这就意味着在统计时间窗内,如果服务调用次数不足 20 次,即使所有的请求都调用出错,熔断器也不会打开。 |
circuitBreaker.errorThresholdPercentage | 错误百分比阈值。 当请求总数在统计时间窗内超过了请求总数阀值,且请求调用出错率超过一定的比例,熔断器才会打开进入熔断开启转态,而这个比例就是错误百分比阈值。错误百分比阈值设置为 50,就表示错误百分比为 50%,如果服务发生了 30 次调用,其中有 15 次发生了错误,即超过了 50% 的错误百分比,这时候将熔断器就会打开。 |
- 在 DeptController 中添加一个 circuitBreakerFallbackMethod() 方法对外提供服务,代码如下。
//服务熔断
@GetMapping("/Hystrix/circuitBreaker/{num}")
public String circuitBreakerFallbackMethod(@PathVariable("num") Integer num){
String info = deptService.deptCircuitBreaker(num);
log.info("request result"+info);
return "request result"+info;
}
- 重启microservice-cloud-provider-dept-hystrix-8004,使用浏览器访问http://127.0.0.1:8004/dept/Hystrix/circuitBreaker/123456,结果如下图。
- 在microservice-cloud-consumer-dept-openFeign的DeptHystrixService接口中补充circuitBreakerFallbackMethod并实现
@GetMapping("/dept/Hystrix/circuitBreaker/{num}")
String circuitBreakerFallbackMethod(@PathVariable("num") Integer num);
- DeptHystrixFallBackServiceImpl类中实现
@Override
public String circuitBreakerFallbackMethod(Integer num) {
return "客户端提示,服务熔断方法执行circuitBreakerFallbackMethod";
}
- DeptHystrixController中添加服务方法circuitBreakerFallbackMethod
@GetMapping("/consumer/dept/Hystrix/circuitBreaker/{num}")
@HystrixCommand
String circuitBreakerFallbackMethod(@PathVariable("num") Integer num){
String info = deptHystrixService.circuitBreakerFallbackMethod(num);
log.info(info);
return info;
}
- 重启 microservice-cloud-consumer-dept-openFeign,使用浏览器访问,访问http://localhost/consumer/dept/Hystrix/circuitBreaker/123456结果如下
- 浏览器多次(调用次数大于请求总数阀值)访问“http://localhost/consumer/dept/Hystrix/circuitBreaker/1234”,使调用出错率大于错误百分比阀值,结果下图。
- 重新将参数修改为大于6位的数字(例如参数为 123456),使用浏览器访问“http://localhost/consumer/dept/Hystrix/circuitBreaker/123456”,会发现在熔断开启状态下,即使我们传入的参数已经是6位数,调用的依然降级逻辑。
- 连续访问“http://localhost/consumer/dept/Hystrix/circuitBreaker/123456”,会发现当服务调用正确率上升到一定的利率后,Hystrix 进入熔断关闭状态。
消费方做降级,提供方做熔断,消费方可以判断哪一部分流量大从而降级使得主要功能能运行,服务方能判断哪个服务挂了做措施,如某个时间段某个服务压力大,那么可以服务器某个不重要的服务关闭了,客户端可以执行客户端备用的降级逻辑立刻返回一个友好的提示,以保障主体业务不受影响,这样将那台服务器供应给这个压力大的服务来缓解压力。
- 服务熔断VS服务降级
服务熔断:服务的某个服务超时或者异常,引起熔断,保险丝
服务降级:客户端从整体网站清求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用。此时在客户端,我们可以准备一个FallbackFactory或Fallback,返回一个默认的值(缺省)。这样虽然整体的服务水平下降了,但是,好歹能用比直按挂掉强。
下一篇:SpringCloud-23-Hystrix 故障监控
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123805.html