Spring Cloud 学习——4.netfix hystrix 实现断路器

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.完

posted @ 2020-02-12 11:19  不爱刺猫的鱼  阅读(335)  评论(0编辑  收藏  举报