08-SpringCloud 之 Hystrix
作者:互联网
什么是 Hystrix
- Hystrix 即:服务熔断器,是用来处理分布式系统的延迟和容错的开源库。
- 在分布式系统中,服务之间的调用会不可避免的调用失败,如超时、异常等,Hystrix 是用来保证在一个依赖出现问题时,不会导致整体服务的失败,避免级联故障的发生,从而提高分布式系统的弹性。
熔断机制
- 熔断机制是对应雪崩效应的一种微服务的链路保护机制
- 当某个服务发生故障,对该服务的请求就会出现失败、超时等问题,此时系统自动开启熔断器,之后此服务不再提供任何业务操作,所有对该服务的请求都会快速失败,直接返回失败信息;这样的话依赖于该服务的其他服务就不会因为得不到回应而造成线程阻塞,从而避免级联故障。
服务熔断与服务降级
- 服务熔断:发生在服务端,就是事先为服务端的方法提供一个备选方案,当该方法出现异常的时候,备选方案自动顶替上去,备选方案返回值与原方法返回值一致,这样就不会导致整个系统奔溃
- 服务降级:发生在客户端,如双 11、618 等大型电商活动期间,导致后端服务器压力剧增,此时可以根据具体业务及流量情况,选择性的关闭一些与活动期间无关的非核心业务,从而释放更多的资源来保证核心业务的正常运作;服务关闭后,客户端将不再进行服务调用而直接返回缺省值
Hystrix 服务熔断配置
服务熔断发生在服务端,重点配置 Provider
-
Provider 的 pom 中添加依赖
pom.xml
<!-- Hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
-
Provider 新建 Controller 定义常规方法并通过 @HystrixCommand 注解为其配置熔断回调方法
DeptHystrixController
package com.kaishen.controller; import com.kaishen.pojo.Dept; import com.kaishen.service.DeptService; 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.PathVariable; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * 部门服务 Hystrix 控制层 * @author : toby * Create in 13:38 2022/5/9 */ @RestController @Slf4j public class DeptHystrixController { @Resource private DeptService deptService; /** * 根据部门编号查询部门信息 * @param id 部门编号 * @return 返回部门信息 */ @GetMapping("/hystrix/dept/get/{id}") @HystrixCommand(fallbackMethod = "hystrixQueryDeptById") public Dept fusingQueryDeptById(@PathVariable Long id) { // 调用查询方法 Dept dept = deptService.queryDeptById(id); log.info("hystrix 查询结果:" + dept); if (null == dept) { throw new RuntimeException("查询异常"); } return dept; } /** * 部门查询熔断方法 * @param id 部门编号 * @return 返回构建的部门实体 */ @SuppressWarnings("unused") public Dept hystrixQueryDeptById(@PathVariable Long id) { return new Dept().setDeptNo(id) .setDeptName("根据 id = " + id + " 查不到对应的部门信息,此处返回熔断信息") .setDbSource("没有数据来源"); } }
-
启动类开启熔断器 @EnableCircuitBreaker
-
Consumer 中通过 Feign 正常调用即可
Hystrix 服务降级配置
服务降级发生在客户端,重点配置 Consumer
-
Consumer 端新增接口
DeptHystrixDemotionService
package com.kaishen.feign.service; import com.kaishen.pojo.Dept; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; /** * 支持服务降级的接口 * @author : toby * Create in 16:52 2022/5/9 */ @Component @FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT", contextId = "3", fallbackFactory = DeptHystrixDemotionServiceFallbackFactory.class) public interface DeptHystrixDemotionService { /** * 根据部门编号查询部门信息 * -- 支持服务降级 * -- application.yml 中开启服务降级后不会再去访问后端系统,此处测试降级功能省略后端方法 * @param id 部门编号 * @return 返回部门信息 */ @GetMapping("/demotion/dept/get/{id}") Dept demotionQueryDeptById(@PathVariable("id") Long id); /** * 说 Hello * -- 定义多个方法,以供回调工厂处理 */ @GetMapping("demotion/hello") void sayHello(); }
-
自定义工厂类,实现 FallbackFactory 接口,将新建的接口作为泛型传入,重写 create 方法
DeptHystrixDemotionServiceFallbackFactory
package com.kaishen.feign.service; import com.kaishen.pojo.Dept; import feign.hystrix.FallbackFactory; import org.springframework.stereotype.Component; /** * 支持服务降级的回调工厂 * @author : toby * Create in 16:57 2022/5/9 */ @Component public class DeptHystrixDemotionServiceFallbackFactory implements FallbackFactory<DeptHystrixDemotionService> { @Override public DeptHystrixDemotionService create(Throwable cause) { return new DeptHystrixDemotionService() { @Override public Dept demotionQueryDeptById(Long id) { return new Dept().setDeptNo(id) .setDeptName("洪峰期,暂不提供此服务") .setDbSource("没有数据来源"); } @Override public void sayHello() { System.out.println("秒杀时刻,服务降级,暂不提供此服务"); } }; } }
-
在新增的接口中开启 Feign 注解,并通过 fallbackFactory 属性指向降级回调工厂
@FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT", contextId = "3", fallbackFactory = DeptHystrixDemotionServiceFallbackFactory.class)
-
application.yml 中开启降级
application.yml
# Feign 配置 feign: hystrix: enabled: true # 开启服务降级
Hystrix Dashboard
-
新建 Module:spring-cloud-dashboard-9001
-
编写 pom 引入依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>spring-cloud-netflix</artifactId> <groupId>com.kaishen</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-cloud-dashboard-9001</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <!-- 引入该模块所需依赖 --> <dependencies> <!-- Dashboard --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency> </dependencies> </project>
-
编写 application.yml
application.yml
server: port: 9001 # Spring 配置 spring: application: name: spring-cloud-dashboard9001 # Dashboard 配置 hystrix: dashboard: proxy-stream-allow-list: "*" # 允许代理的主机列表
-
编写启动类,开启注解
DashboardApplication9001
package com.kaishen; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; /** * 监控服务启动类 * @author : toby * Create in 19:24 2022/5/9 */ @SpringBootApplication @EnableHystrixDashboard public class DashboardApplication9001 { public static void main(String[] args) { SpringApplication.run(DashboardApplication9001.class, args); } }
-
启动 Dashboard 可看到如下界面,则 Dashboard 配置成功
-
被监控的服务中需要引入 actuator 及 Hystrix 依赖
pom.xml
<!-- SpringBoot 监控 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
-
被监控服务的启动类中添加 hystrixMetricsStreamServlet,并开启 @EnableHystrix 注解
DeptHystrixProviderApplication8004
package com.kaishen; 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.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.context.annotation.Bean; /** * 部门服务提供者启动类 * @author : toby * Create in 10:56 2022/5/10 */ @SpringBootApplication @EnableEurekaClient @EnableHystrix public class DeptHystrixProviderApplication8004 { public static void main(String[] args) { SpringApplication.run(DeptHystrixProviderApplication8004.class, args); } /** * 注册监控页面 * @return hystrixMetricsStreamServletServletRegistrationBean */ @Bean public ServletRegistrationBean<HystrixMetricsStreamServlet> hystrixMetricsStreamServlet() { ServletRegistrationBean<HystrixMetricsStreamServlet> hystrixMetricsStreamServletServletRegistrationBean = new ServletRegistrationBean<>(new HystrixMetricsStreamServlet()); hystrixMetricsStreamServletServletRegistrationBean.addUrlMappings("/actuator/hystrix.stream"); return hystrixMetricsStreamServletServletRegistrationBean; } }
注意注意注意:
- 被监控服务 Controller 中的所有方法都必须要有 @HystrixCommand() 熔断实现,否则 Dashboard 无法正常显示
- 先对被监控服务进行一次正常访问如:
http://localhost:8004/hystrix/dept/get/1
-
被监控服务的 Controller
DeptHystrixController
package com.kaishen.controller; import com.kaishen.pojo.Dept; import com.kaishen.service.DeptService; 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.PathVariable; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * 部门服务 Hystrix 控制层 * @author : toby * Create in 13:40 2022/5/9 */ @RestController @Slf4j public class DeptHystrixController { @Resource private DeptService deptService; // region fusingQueryDeptById /** * 根据部门编号查询部门信息 * @param id 部门编号 * @return 返回部门信息 */ @GetMapping("/hystrix/dept/get/{id}") @HystrixCommand(fallbackMethod = "hystrixQueryDeptById") public Dept fusingQueryDeptById(@PathVariable Long id) { // 调用查询方法 Dept dept = deptService.queryDeptById(id); log.info("hystrix 查询结果:" + dept); if (null == dept) { throw new RuntimeException("查询异常"); } return dept; } /** * 部门查询熔断方法 * @param id 部门编号 * @return 返回构建的部门实体 */ @SuppressWarnings("unused") public Dept hystrixQueryDeptById(@PathVariable Long id) { return new Dept().setDeptNo(id) .setDeptName("根据 id = " + id + " 查不到对应的部门信息,此处返回熔断信息") .setDbSource("没有数据来源"); } // endregion // region sayHello /** * 说 Hello * 此方法无意义,只用于定义多个方法供回调工厂处理 * @param id 入参 * @return 返回字符串 */ @GetMapping("/hystrix/dept/get/map/{id}") @HystrixCommand(fallbackMethod = "toSayHello") public String sayHello(@PathVariable Long id) { int i = 2; if (id == i) { throw new RuntimeException("报错啦"); } System.out.println("Hello"); return "Hello"; } @SuppressWarnings("unused") public String toSayHello(@PathVariable Long id) { System.out.println(id); return "toSayHello"; } // endregion }
-
在 Dashboard 界面,填写要被监控的流信息,如下图
-
进入后即可看到监控页面
标签:hystrix,Hystrix,SpringCloud,08,springframework,public,import,org,id 来源: https://www.cnblogs.com/xiaokai007/p/16321731.html