官方介绍:https://github.com/Netflix/Hystrix/wiki
在现代的分布式系统中,通常一个服务会依赖多个其他的服务
这就是Hystrix的目的所在,通过某些手段,提高系统的容灾性能
服务雪崩与服务熔断
区分服务熔断和服务降级
https://zhuanlan.zhihu.com/p/341939685
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
server: port: 8001 spring: application: name: provider-eureka datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/cloud-db01?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true username: root password: 123456 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.pbx.springcloud.pojo eureka: client: service-url: defaultZone: http://eureka7000:7000/eureka/, http://eureka7001:7001/eureka/, http://eureka7002:7002/eureka/, http://eureka7003:7003/eureka/, http://eureka7004:7004/eureka/ fetch-registry: true # 作为服务提供商,需要到Eureka中注册一下 register-with-eureka: true instance: instance-id: BruceXu:Eureka Provider:8001
@SpringBootApplication @EnableEurekaClient @EnableCircuitBreaker public class HystrixApplication { public static void main(String[] args) { SpringApplication.run(HystrixApplication.class, args); } }
@RestController @RequestMapping("/provider") public class DepartmentController { @Autowired private DepartmentService service; @Value("${eureka.instance.instance-id}") private String source; @GetMapping("/get/{id}") @HystrixCommand(fallbackMethod = "fallbackGet") public Message getDepartmentById(@PathVariable("id") Long id) { Department res = service.getDepartmentById(id); if (res == null) { throw new RuntimeException("找不到"); } return new Message(200, "hystrix", "查找成功", res); } // 回调方法的参数要和原方法的参数保持一致 public Message fallbackGet(@PathVariable Long id) { return new Message(303, "hystrix", "查找失败,这是Hystrix的失败回调", new Department().setId(id).setName("hystrix fallback")); } @GetMapping("/get/all") public Message getAllDepartment(HttpServletRequest request) { log.info(request.getRemoteAddr() + " try to get department list"); List<Department> list = service.getDepartmentList(); if (list.size() > 0) { log.info("search success, + department nums = " + list.size()); return new Message(200, source, "查找成功", list); } else { log.info("search failed"); return new Message(400, source, "查找失败"); } } }
相比于服务熔断,是在服务端做手脚。服务降级则是在客户端做手脚
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
# 开启hystrix feign: hystrix: enabled: true
@SpringBootApplication @EnableEurekaClient @EnableFeignClients("com.pbx.springcloud") public class FeignConsumer { public static void main(String[] args) { SpringApplication.run(FeignConsumer.class, args); } }
@Component public class FallbackService implements FallbackFactory<FeignService> { @Override public FeignService create(Throwable throwable) { return new FeignService() { @Override public Message add(Department department) { return null; } @Override public Message getDepartmentById(Long id) { return new Message(304, "client", "服务暂时不可用"); } @Override public Message getDepartmentList() { return null; } }; } }
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency>
启动类
@EnableHystrixDashboard @SpringBootApplication public class DashboardApplication { public static void main(String[] args) { SpringApplication.run(DashboardApplication.class, args); } }
增加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
增加对外提供监控信息的servlet bean
@Bean public ServletRegistrationBean hystrixDashboard() { ServletRegistrationBean bean = new ServletRegistrationBean(new HystrixMetricsStreamServlet()); bean.addUrlMappings("/actuator/hystrix.stream"); return bean; }
增加配置
management: endpoints: web: exposure: include: hystrix.stream