赞
踩
目录
5.appliction.yml 中添加配置,在客户端配置请求超时的时间
在微服务架构中,一个应用往往由多个服务组成,这些服务之间相互依赖,依赖关系错综复杂。
当服务 E 发生故障或网络延迟时,会出现以下情况:
1.即使其他所有服务都可用,由于服务 E 的不可用,那么用户请求 1、2、3 都会处于阻塞状态,等待服务 E 的响应。在高并发的场景下,会导致整个服务器的线程资源在短时间内迅速消耗殆尽
2.所有依赖于服务 E 的其他服务,例如服务 B、D 以及 F 也都会处于线程阻塞状态,等待服务 E 的响应,导致这些服务的不可用
3.所有依赖服务B、D 和 F 的服务,例如服务 A 和服务 C 也会处于线程阻塞状态,以等待服务 D 和服务 F 的响应,导致服务 A 和服务 C 也不可用
当微服务系统的一个服务出现故障时,故障会沿着服务的调用链路在系统中疯狂蔓延,最终导致整个微服务系统的瘫痪,这就是“雪崩效应”。为了防止此类事件的发生,微服务架构引入了“熔断器”的一系列服务容错和保护机制。
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,可以保证一个服务出现故障时,不会导致整个系统出现雪崩效应,以提高分布式系统的弹性。
作为“断路器”,在一个服务出现故障时,可以通过短路器监控,返回一个可以处理的响应结果,保证服务调用线程不会被长时间占用,避免故障蔓延。
保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源
快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败
提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法
防止故障扩散:使用熔断机制,防止故障扩散到其他服务
监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态
服务出现故障时,给故障服务降级到事先准备好的故障处理结果,将此结果返回给服务消费者;
如:
客户端访问服务1,服务1调用服务2,服务2出现故障,Hystrix服务降级,返回一个可以处理的结果给服务1,服务1再以友好的错误界面返回给客户端
1.在服务器压力剧增时,根据实际业务情况及流量,对一些不重要、不紧急的服务进行有策略地不处理或简单处理,从而释放服务器资源以保证核心服务正常运作。
2.当某些服务不可用时,为了避免长时间等待造成服务卡顿或雪崩效应,而主动执行备用的降级逻辑立刻返回一个友好的提示,以保障主体业务不受影响
- <!--hystrix 依赖-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
- </dependency>
- public interface DeptService {
-
- // hystrix 熔断器示例 ok
- public String deptInfo_Ok(Integer id);
-
- //hystrix 熔断器超时案例
- public String deptInfo_Timeout(Integer id);
- }
- @Service("deptService")
- public class DeptServiceImpl implements DeptService {
- @Override
- public String deptInfo_Ok(Integer id) {
- return "线程池:" + Thread.currentThread().getName() + " deptInfo_Ok,id: " + id;
- }
- //一旦该方法失败并抛出了异常信息后,会自动调用 @HystrixCommand 注解标注的 fallbackMethod 指定的方法
- @HystrixCommand(fallbackMethod = "dept_TimeoutHandler",
- commandProperties =
- //规定 5 秒钟以内就不报错,正常运行,超过 5 秒就报错,调用指定的方法
- {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")})
- @Override
- public String deptInfo_Timeout(Integer id) {
- int outTime = 6;
- try {
- TimeUnit.SECONDS.sleep(outTime);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return "线程池:" + Thread.currentThread().getName() + " deptInfo_Timeout,id: " + id + " 耗时: " + outTime;
- }
- // 当服务出现故障后,调用该方法给出友好提示
- public String dept_TimeoutHandler(Integer id) {
- return "C语言中文网提醒您,系统繁忙请稍后再试!"+"线程池:" + Thread.currentThread().getName() + " deptInfo_Timeout,id: " + id;
- }
- }

@HystrixCommand 注解:
参数 fallbackMethod 属性用于指定降级方法
参数 execution.isolation.thread.timeoutInMilliseconds 用于设置自身调用超时时间的峰值,峰值内可以正常运行,否则执行降级方法
- @RestController
- @Slf4j
- public class DeptController {
- @Autowired
- private DeptService deptService;
- @Value("${server.port}")
- private String serverPort;
- @RequestMapping(value = "/dept/hystrix/ok/{id}")
- public String deptInfo_Ok(@PathVariable("id") Integer id) {
- String result = deptService.deptInfo_Ok(id);
- log.info("端口号:" + serverPort + " result:" + result);
- return result + ", 端口号:" + serverPort;
- }
- // Hystrix 服务超时降级
- @RequestMapping(value = "/dept/hystrix/timeout/{id}")
- public String deptInfo_Timeout(@PathVariable("id") Integer id) {
- String result = deptService.deptInfo_Timeout(id);
- log.info("端口号:" + serverPort + " result:" + result);
- return result + ", 端口号:" + serverPort;
- }
- }

- @SpringBootApplication
- @EnableEurekaClient //开启 Eureka 客户端功能
- @EnableCircuitBreaker //激活熔断器功能
- public class MicroServiceCloudProviderDeptHystrix8004Application {
- public static void main(String[] args) {
- SpringApplication.run(MicroServiceCloudProviderDeptHystrix8004Application.class, args);
- }
- }
通常情况下,我们都会在客户端进行服务降级,当客户端调用的服务端的服务不可用时,客户端直接进行服务降级处理,避免其线程被长时间、不必要地占用
- <!--hystrix 依赖-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
- </dependency>
application.yml 中添加以下配置,开启客户端的 Hystrix 功能
- feign:
- hystrix:
- enabled: true #开启客户端 hystrix
- @Component
- @FeignClient(value = "MICROSERVICECLOUDPROVIDERDEPTHYSTRIX")
- public interface DeptHystrixService {
- @RequestMapping(value = "/dept/hystrix/ok/{id}")
- public String deptInfo_Ok(@PathVariable("id") Integer id);
- @RequestMapping(value = "/dept/hystrix/timeout/{id}")
- public String deptInfo_Timeout(@PathVariable("id") Integer id);
- }
- @Slf4j
- @RestController
- public class HystrixController_Consumer {
- @Resource
- private DeptHystrixService deptHystrixService;
- @RequestMapping(value = "/consumer/dept/hystrix/ok/{id}")
- public String deptInfo_Ok(@PathVariable("id") Integer id) {
- return deptHystrixService.deptInfo_Ok(id);
- }
- //在客户端进行降级
- @RequestMapping(value = "/consumer/dept/hystrix/timeout/{id}")
- @HystrixCommand(fallbackMethod = "dept_TimeoutHandler") //为该请求指定专属的回退方法
- public String deptInfo_Timeout(@PathVariable("id") Integer id) {
- String s = deptHystrixService.deptInfo_Timeout(id);
- log.info(s);
- return s;
- }
- // deptInfo_Timeout方法的 专用 fallback 方法
- public String dept_TimeoutHandler(@PathVariable("id") Integer id) {
- log.info("deptInfo_Timeout 出错,服务已被降级!");
- return "C语言中文网提醒您:服务端系统繁忙,请稍后再试!(客户端 deptInfo_Timeout 专属的回退方法触发)";
- }
- }

- ######################### Ribbon 客户端超时控制 ###################################
- ribbon:
- ReadTimeout: 6000 #建立连接所用的时间,适用于网络状况正常的情况下,两端两端连接所用的时间
- ConnectionTimeout: 6000 #建立连接后,服务器读取到可用资源的时间
- ######################配置请求超时时间##########################
- hystrix:
- command:
- default:
- execution:
- isolation:
- thread:
- timeoutInMilliseconds: 7000
- ####################配置具体方法超时时间 为 3 秒########################
- DeptHystrixService#deptInfo_Timeout(Integer):
- execution:
- isolation:
- thread:
- timeoutInMilliseconds: 3000

注意:
1.Hystrix 可以来为所有请求(方法)设置超时时间(单位为毫秒),若请求超时则触发全局的回退方法进行处理
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=mmm
2.Hystrix 还可以为某个特定的服务请求(方法)设置超时时间
hystrix.command.xxx#yyy(zzz).execution.isolation.thread.timeoutInMilliseconds=mmm
格式说明如下:
- @SpringBootApplication
- @EnableFeignClients //开启 OpenFeign 功能
- @EnableHystrix //启用 Hystrix
- public class MicroServiceCloudConsumerDeptFeignApplication {
- public static void main(String[] args) {
- SpringApplication.run(MicroServiceCloudConsumerDeptFeignApplication.class, args);
- }
- }
针对所有业务方法都配置降级方法,这极有可能会造成代码的急剧膨胀。为了解决该问题,我们还可以为所有业务方法指定一个全局的回退方法
- @Slf4j
- @RestController
- @DefaultProperties(defaultFallback = "dept_Global_FallbackMethod") //全局的服务降级方法
- public class HystrixController_Consumer {
- ……
- }
创建一个名为 dept_Global_FallbackMethod 的全局回退方法
- /**
- * 全局的 fallback 方法,
- * 回退方法必须和 hystrix 的执行方法在相同类中
- * @DefaultProperties(defaultFallback = "dept_Global_FallbackMethod") 类上注解,请求方法上使用 @HystrixCommand 注解
- */
- public String dept_Global_FallbackMethod() {
- return "C语言中文网提醒您,运行出错或服务端系统繁忙,请稍后再试!(客户端全局回退方法触发,)";
- }
降级(FallBack)方法必须与其对应的业务方法在同一个类中,否则无法生效
在所有的业务方法上都标注 @HystrixCommand 注解,将 deptInfo_Timeout() 方法上的 @HystrixCommand(fallbackMethod = "dept_TimeoutHandler") 修改为 @HystrixCommand 即可
- //在客户端进行降级
- @RequestMapping(value = "/consumer/dept/hystrix/timeout/{id}")
- @HystrixCommand
- public String deptInfo_Timeout(@PathVariable("id") Integer id) {
- String s = deptHystrixService.deptInfo_Timeout(id);
- log.info(s);
- return s;
- }
全局降级方法的优先级较低,只有业务方法没有指定其降级方法时,服务降级时才会触发全局回退方法。若业务方法指定它自己的回退方法,那么在服务降级时,就只会直接触发它自己的回退方法,而非全局回退方法。
熔断机制是应对服务雪崩的一种链路保护机制,当服务出现故障时,服务会进行降级,熔断该服务节点,迅速返回错误响应信息。当检测到服务访问正常时,恢复其链路节点
①circuitBreaker.enabled:是否开启熔断;
②circuitBreaker.requestVolumeThreshold:当前服务失败几次后开启断路,默认20次;
③circuitBreaker.sleepWindowInMilliseconds:设置断路时间,过了该时间后会尝试恢复,在断路时间内,即使请求正确也会走降级方法;
在熔断机制中涉及了三种熔断类型:
熔断打开后,在此时间内不会对该服务进行调用,而是直接访问降级方法。通过设置熔断时间,当达到该时间后,会尝试恢复该服务
熔断关闭代表服务正常,不会干扰正常服务调用。
熔断半开时,请求可以访问服务,若请求正常访问,则熔断会关闭;若请请求不正常,继续熔断,调用降级方法。
熔断机制是通过 Hystrix 实现的。Hystrix 会监控微服务间调用的状况,当失败调用到一定比例时(例如 5 秒内失败 20 次),就会启动熔断机制
1.当服务的调用出错率达到或超过 Hystix 规定的比率(默认为 50%)后,熔断器进入熔断开启状态。
2.熔断器进入熔断开启状态后,Hystrix 会启动一个休眠时间窗,在这个时间窗内,该服务的降级逻辑会临时充当业务主逻辑,而原来的业务主逻辑不可用。
3.当有请求再次调用该服务时,会直接调用降级逻辑快速地返回失败响应,以避免系统雪崩。
4.当休眠时间窗到期后,Hystrix 会进入半熔断转态,允许部分请求对服务原来的主业务逻辑进行调用,并监控其调用成功率。
5.如果调用成功率达到预期,则说明服务已恢复正常,Hystrix 进入熔断关闭状态,服务原来的主业务逻辑恢复;否则 Hystrix 重新进入熔断开启状态,休眠时间窗口重新计时,继续重复第 2 到第 5 步。
- public interface DeptService {
- // hystrix 熔断器示例 ok
- public String deptInfo_Ok(Integer id);
-
- //hystrix 熔断器超时案例
- public String deptInfo_Timeout(Integer id);
- // Hystrix 熔断机制案例
- public String deptCircuitBreaker(Integer id);
- }
实现类 DeptServiceImpl 添加 deptCircuitBreaker() 的方法实现及其回退方法
- //Hystrix 熔断案例
- @Override
- @HystrixCommand(fallbackMethod = "deptCircuitBreaker_fallback", commandProperties = {
- //以下参数在 HystrixCommandProperties 类中有默认配置
- @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //是否开启熔断器
- @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "1000"), //统计时间窗
- @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //统计时间窗内请求次数
- @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗口期
- @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"), //在统计时间窗口期以内,请求失败率达到 60% 时进入熔断状态
- })
- public String deptCircuitBreaker(Integer id) {
- if (id < 0) {
- //当传入的 id 为负数时,抛出异常,调用降级方法
- throw new RuntimeException("c语言中文网提醒您,id 不能是负数!");
- }
- String serialNum = IdUtil.simpleUUID();
- return Thread.currentThread().getName() + "\t" + "调用成功,流水号为:" + serialNum;
- }
- //deptCircuitBreaker 的降级方法
- public String deptCircuitBreaker_fallback(Integer id) {
- return "c语言中文网提醒您,id 不能是负数,请稍后重试!\t id:" + id;
- }

- // Hystrix 服务熔断
- @RequestMapping(value = "/dept/hystrix/circuit/{id}")
- public String deptCircuitBreaker(@PathVariable("id") Integer id){
- String result = deptService.deptCircuitBreaker(id);
- log.info("result:"+result);
- return result;
- }
Hystrix 还提供了准实时的调用监控功能,Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表的形式展示给用户,包括每秒执行请求的数量、成功请求的数量和失败请求的数量等
1.添加依赖
- <!--hystrix-dashboard 监控的依赖-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
- </dependency>
2.application.yml 中添加配置
- #http://eureka7001.com:9002/hystrix 熔断器监控页面
- # localhost:8004//actuator/hystrix.stream 监控地址
- hystrix:
- dashboard:
- proxy-stream-allow-list:
- - "localhost"
3.主启动类上添加 @EnableHystrixDashboard 注解,开启 Hystrix 监控功能
- @SpringBootApplication
- @EnableHystrixDashboard
- public class MicroServiceCloudConsumerDeptHystrixDashboard9002Application {
- public static void main(String[] args) {
- SpringApplication.run(MicroServiceCloudConsumerDeptHystrixDashboard9002Application.class, args);
- }
- }
4.创建配置类
- @Configuration
- public class HystrixDashboardConfig {
- /**
- * Hystrix dashboard 监控界面必须配置
- * @return
- */
- @Bean
- public ServletRegistrationBean getServlet() {
- HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
- ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
- registrationBean.setLoadOnStartup(1);
- registrationBean.addUrlMappings("/actuator/hystrix.stream");//访问路径
- registrationBean.setName("hystrix.stream");
- return registrationBean;
- }
- }

5.浏览器访问
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。