1.前言
在一个微服务系统中,不同服务之间相互调用,可能形成一些调用链。那么当下游的的某一个服务故障时,可能会导致级联故障(即导致直接或者间接调用该服务的所有上游服务都不可用)。为了解决这种问题,就需要引入断路器。断路器的作用是:在调用服务的方法中声明一个断路节点,当本次调用服务失败时,根据节点声明的处理方式进行处理,避免抛出异常。
spring cloud 提供了四种断路器实现:Netflix Hystrix、 Resilience4J、Sentinel、Spring Retry 。本文实现 Netfix Hystrix 的简单示例。
2.添加依赖
spring boot 1.x 环境下,添加依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.x.x.RELEASE</version> </dependency>
spring boot 2.x 环境下,添加依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.x.x.RELEASE</version> </dependency>
3.启用断路器
启动类添加注解 @EnableCircuitBreaker 。
4.编写服务提供者
@RestController @RequestMapping("/user") public class UserController { @GetMapping("/get/{id}") public User get(@PathVariable("id")String id){ System.out.println("/user/get/{id},id=" + id); User user = new User(); user.setId(id); user.setUsername("onezai"); user.setPassword("123456"); user.setMobile("13128921555"); return user; } }
5.编写 feign 服务调用接口
@FeignClient("sys") public interface UserClient { @GetMapping(value = "/sys/user/get/{id}") User getUserById(@PathVariable("id") String id); }
6.编写服务调用者
@RestController @RequestMapping("/") public class HomeController { @Autowired EurekaClient eurekaClient; @Autowired RestTemplate restTemplate; @Autowired UserClient userClient; @GetMapping("/getUser/{id}") @HystrixCommand(fallbackMethod = "getUserDefault") public User getUser(@PathVariable("id")String id){ User user = userClient.getUserById(id); System.out.println("user:\n" + JSONObject.fromObject(user).toString()); return user; }
其中 @HystrixCommand(fallbackMethod = "getUserDefault") 声明了一个断路节点,指定当调用的服务不可用时,回退到 getUserDefault 方法,下面是该方法的实现:
public User getUserDefault(String id){ User user = new User(); user.setId(id); user.setUsername("defaultUser"); user.setPassword("defaultPass"); user.setMobile("13122225555"); return user;}
7.验证结果
7.1.首先我们来验证正常情况下的结果:
7.2.接下来我们验证异常的情况:
首先我们将该行 @GetMapping("/get/{id}") 代码注释掉,这样也就人为地创造了服务不可用的条件,测试
断路成功。
8.注意
值得注意的是:fallbackMethod 指定的方法必须与 HystrixCommand 注解作用的方法参数一致,否则会报错:
com.netflix.hystrix.contrib.javanica.exception.FallbackDefinitionException: fallback method wasn‘t found: getUserDefault([class java.lang.String])
at com.netflix.hystrix.contrib.javanica.utils.MethodProvider$FallbackMethodFinder.doFind(MethodProvider.java:190) ~[hystrix-javanica-1.5.18.jar:1.5.18]
at com.netflix.hystrix.contrib.javanica.utils.MethodProvider$FallbackMethodFinder.find(MethodProvider.java:159) ~[hystrix-javanica-1.5.18.jar:1.5.18]
at com.netflix.hystrix.contrib.javanica.utils.MethodProvider.getFallbackMethod(MethodProvider.java:73) ~[hystrix-javanica-1.5.18.jar:1.5.18]
at com.netflix.hystrix.contrib.javanica.utils.MethodProvider.getFallbackMethod(MethodProvider.java:59) ~[hystrix-javanica-1.5.18.jar:1.5.18]
at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect.setFallbackMethod(HystrixCommandAspect.java:331) ~[hystrix-javanica-1.5.18.jar:1.5.18]
······
9.完
原文地址:https://www.cnblogs.com/coding-one/p/12298279.html