zoukankan      html  css  js  c++  java
  • 从零开始学spring cloud(十) -------- hystrix简单代码示例

    一、官网文档阅读

     

    较低级别的服务中的服务故障可能导致级联故障一直到用户。 当对特定服务的调用超过circuitBreaker.requestVolumeThreshold(默认值:20个请求)且失败百分比大于circuit.rolllingStats.timeInMilliseconds定义的滚动窗口中的circuitBreaker.errorThresholdPercentage(默认值:> 50%)时(默认值:10秒) ,电路打开,没有拨打电话。 在出现错误和开路的情况下,开发人员可以提供回退。

    二、示例

    添加hystrix依赖

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>

     修改movie服务的controller

     1 package com.zwjk.cloud.controller;
     2 
     3 import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
     4 import com.zwjk.cloud.entity.User;
     5 import org.springframework.beans.factory.annotation.Autowired;
     6 import org.springframework.beans.factory.annotation.Value;
     7 import org.springframework.cloud.client.ServiceInstance;
     8 import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
     9 import org.springframework.web.bind.annotation.GetMapping;
    10 import org.springframework.web.bind.annotation.PathVariable;
    11 import org.springframework.web.bind.annotation.RestController;
    12 import org.springframework.web.client.RestTemplate;
    13 
    14 /**
    15  * @author : Jixiaohu
    16  * @Date : 2019-04-11.
    17  * @Time : 9:38.
    18  * @Description :
    19  */
    20 @RestController
    21 public class MovieController {
    22 
    23     @Autowired
    24     private RestTemplate restTemplate;
    25 
    26     @Value("${user.userServicePath}")
    27     private String userServicePath;
    28 
    29     @GetMapping("/movie/{id}")
    30     @HystrixCommand(fallbackMethod = "findByIdFallback")
    31     public User findById(@PathVariable Long id) {
    32         return this.restTemplate.getForObject(this.userServicePath + id, User.class);
    33     }
    34 
    35 
    36     public User findByIdFallback(Long id) {
    37         User user = new User();
    38         user.setId(0L);
    39         user.setName("失败");
    40         return user;
    41     }
    42 }

    这边需要注意的是,fallbackMethod方法的返回值和入参,必须和原方法一致,下面进行测试:

    可以看到,这里返回了正常的结果,下面停掉user服务

     可以看到,这里返回的结果,就是fallbackMethod里面返回的内容,hystrix就起了作用。

    下面,继续看一下

    Feign Hystrix Support

     参考官网使用示例:

     1 @FeignClient(name = "hello", fallback = HystrixClientFallback.class)
     2 protected interface HystrixClient {
     3     @RequestMapping(method = RequestMethod.GET, value = "/hello")
     4     Hello iFailSometimes();
     5 }
     6 
     7 static class HystrixClientFallback implements HystrixClient {
     8     @Override
     9     public Hello iFailSometimes() {
    10         return new Hello("fallback");
    11     }
    12 }

    在配置文件中,增加开启feign使用断路器

    feign:
      hystrix:
        enabled: true

    按照示例,我们在movie服务中,新增UserFeignClientFallback类

     1 package com.zwjk.cloud.fegin;
     2 
     3 import com.zwjk.cloud.entity.User;
     4 import org.springframework.stereotype.Component;
     5 
     6 /**
     7  * @author : Jixiaohu
     8  * @Date : 2019-04-17.
     9  * @Time : 18:20.
    10  * @Description :
    11  */
    12 @Component
    13 public class UserFeignClientFallback implements UserFeignClient {
    14     @Override
    15     public User findById(Long id) {
    16         User user = new User();
    17         user.setId(0L);
    18         return user;
    19     }
    20 }

    在fegin上增加相应的注解:

     1 package com.zwjk.cloud.fegin;
     2 
     3 import com.zwjk.cloud.entity.User;
     4 import org.springframework.cloud.openfeign.FeignClient;
     5 import org.springframework.web.bind.annotation.GetMapping;
     6 import org.springframework.web.bind.annotation.PathVariable;
     7 import org.springframework.web.bind.annotation.PostMapping;
     8 import org.springframework.web.bind.annotation.RequestBody;
     9 
    10 /**
    11  * @author : Jixiaohu
    12  * @Date : 2019-04-12.
    13  * @Time : 16:50.
    14  * @Description :
    15  */
    16 @FeignClient(name = "microservice-provider-user", fallback = UserFeignClientFallback.class)
    17 public interface UserFeignClient {
    18     //@PathVariable得设置value
    19     @GetMapping("/simple/{id}")
    20     User findById(@PathVariable("id") Long id); //@PathVariable得设置value
    21 }

     启动项目,进行测试,

    同样的,停掉user服务,再次访问这个地址:

    就可以实现熔断服务

    当一个项目中,有个feign时,如何禁用一些feign的hystrix?

    查看一下官网文档

    通过配置加上feignBuilder,就可以禁用指定fegin的hystrix

    查看一下代码实现:

     1 package com.zwjk.cloud.controller;
     2 
     3 import com.zwjk.cloud.entity.User;
     4 import com.zwjk.cloud.fegin.UserFeignClient2;
     5 import com.zwjk.cloud.fegin.UserFeignClient;
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.web.bind.annotation.GetMapping;
     8 import org.springframework.web.bind.annotation.PathVariable;
     9 import org.springframework.web.bind.annotation.RestController;
    10 
    11 /**
    12  * @author : Jixiaohu
    13  * @Date : 2019-04-11.
    14  * @Time : 9:38.
    15  * @Description :
    16  */
    17 @RestController
    18 public class MovieController {
    19 
    20     @Autowired
    21     private UserFeignClient userFeignClient;
    22 
    23     @Autowired
    24     private UserFeignClient2 userFeignClient2;
    25 
    26     @GetMapping("/movie/{id}")
    27     public User findById(@PathVariable Long id) {
    28         return this.userFeignClient.findById(id);
    29     }
    30 
    31     @GetMapping("/{serviceName}")
    32     public String findServiceInfoFromEurekaByServiceName(@PathVariable String serviceName) {
    33         return this.userFeignClient2.findServiceInfoFromEurekaByServiceName(serviceName);
    34     }
    35 
    36 
    37 }

     两个fegin:

     1 package com.zwjk.cloud.fegin;
     2 
     3 import com.zwjk.cloud.entity.User;
     4 import com.zwjk.config.UserConfiguration;
     5 import feign.Param;
     6 import feign.RequestLine;
     7 import org.springframework.cloud.openfeign.FeignClient;
     8 
     9 /**
    10  * @author : Jixiaohu
    11  * @Date : 2019-04-12.
    12  * @Time : 16:50.
    13  * @Description :
    14  */
    15 @FeignClient(name = "microservice-provider-user", configuration = UserConfiguration.class, fallback =
    16     UserFeignClientFallback.class)
    17 public interface UserFeignClient {
    18     //@PathVariable得设置value
    19     @RequestLine("GET /simple/{id}")
    20     User findById(@Param("id") Long id); //@PathVariable得设置value
    21 
    22 }
     1 package com.zwjk.cloud.fegin;
     2 
     3 import com.zwjk.config.UserConfiguration2;
     4 import org.springframework.cloud.openfeign.FeignClient;
     5 import org.springframework.web.bind.annotation.PathVariable;
     6 import org.springframework.web.bind.annotation.RequestMapping;
     7 
     8 /**
     9  * @author : Jixiaohu
    10  * @Date : 2019-04-13.
    11  * @Time : 11:23.
    12  * @Description :
    13  */
    14 @FeignClient(name = "xxxx", url = "http://192.168.1.114:8761/", configuration = UserConfiguration2.class)
    15 public interface UserFeignClient2 {
    16     @RequestMapping(value = "/eureka/apps/{serviceName}")
    17     public String findServiceInfoFromEurekaByServiceName(@PathVariable("serviceName") String serviceName);
    18 }

    两个fallback

     1 package com.zwjk.cloud.fegin;
     2 
     3 import org.springframework.stereotype.Component;
     4 
     5 /**
     6  * @author : Jixiaohu
     7  * @Date : 2019-04-17.
     8  * @Time : 18:20.
     9  * @Description :
    10  */
    11 @Component
    12 public class UserFeignClient2Fallback implements UserFeignClient2 {
    13 
    14     @Override
    15     public String findServiceInfoFromEurekaByServiceName(String serviceName) {
    16         return "hahahha";
    17     }
    18 }
     1 package com.zwjk.cloud.fegin;
     2 
     3 import com.zwjk.cloud.entity.User;
     4 import org.springframework.stereotype.Component;
     5 
     6 /**
     7  * @author : Jixiaohu
     8  * @Date : 2019-04-17.
     9  * @Time : 18:20.
    10  * @Description :
    11  */
    12 @Component
    13 public class UserFeignClientFallback implements UserFeignClient {
    14     @Override
    15     public User findById(Long id) {
    16         User user = new User();
    17         user.setId(0L);
    18         return user;
    19     }
    20 }

     看一下两个配置文件

     1 package com.zwjk.config;
     2 
     3 import feign.Contract;
     4 import feign.Logger;
     5 import org.springframework.context.annotation.Bean;
     6 import org.springframework.context.annotation.Configuration;
     7 
     8 /**
     9  * @author : Jixiaohu
    10  * @Date : 2019-04-13.
    11  * @Time : 10:20.
    12  * @Description :
    13  */
    14 @Configuration
    15 public class UserConfiguration {
    16 
    17     @Bean
    18     public Contract feignContract() {
    19         return new feign.Contract.Default();
    20     }
    21 
    22     @Bean
    23     Logger.Level feignLoggerLevel() {
    24         return Logger.Level.FULL;
    25     }
    26 }
     1 package com.zwjk.config;
     2 
     3 import feign.Feign;
     4 import feign.auth.BasicAuthRequestInterceptor;
     5 import org.springframework.context.annotation.Bean;
     6 import org.springframework.context.annotation.Configuration;
     7 import org.springframework.context.annotation.Scope;
     8 
     9 /**
    10  * @author : Jixiaohu
    11  * @Date : 2019-04-13.
    12  * @Time : 11:25.
    13  * @Description :
    14  */
    15 @Configuration
    16 public class UserConfiguration2 {
    17     @Bean
    18     public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
    19         return new BasicAuthRequestInterceptor("user", "password123");
    20     }
    21 
    22     @Configuration
    23     public class FooConfiguration {
    24         @Bean
    25         @Scope("prototype")
    26         public Feign.Builder feignBuilder() {
    27             return Feign.builder();
    28         }
    29     }
    30 }

     启动服务,进行测试

     

    下面,我们停掉eureka,和user服务,在一次查看返回结果

    启用hystrix的返回结果如下:

    没有启用hystrix的返回结果,提示500错误

    从中,可以看出,hytrix的熔断,可以有很细的粒度。

     如果想要查看fallback回退的原因,可以使用可以使用@FeignClient中的fallbackFactory属性。

    看一下如何实现?

    参考一下官网文档:

    先写一个hystrixFactory:

     1 package com.zwjk.cloud.fegin;
     2 
     3 import com.zwjk.cloud.entity.User;
     4 import feign.hystrix.FallbackFactory;
     5 import org.slf4j.Logger;
     6 import org.slf4j.LoggerFactory;
     7 import org.springframework.stereotype.Component;
     8 
     9 /**
    10  * @author : Jixiaohu
    11  * @Date : 2019-04-17.
    12  * @Time : 19:37.
    13  * @Description :
    14  */
    15 @Component
    16 public class UserFeginClientFactory implements FallbackFactory<UserFeignClient> {
    17 
    18     private static final Logger Log = LoggerFactory.getLogger(UserFeginClientFactory.class);
    19 
    20     @Override
    21     public UserFeignClient create(Throwable cause) {
    22         UserFeginClientFactory.Log.info("fallback:reason was : {}", cause.getMessage());
    23         return id -> {
    24             User user = new User();
    25             user.setId(-1L);
    26             user.setName("haha");
    27             return user;
    28         };
    29     }
    30 }

     修改一下原feignClient

     1 package com.zwjk.cloud.fegin;
     2 
     3 import com.zwjk.cloud.entity.User;
     4 import org.springframework.cloud.openfeign.FeignClient;
     5 import org.springframework.web.bind.annotation.GetMapping;
     6 import org.springframework.web.bind.annotation.PathVariable;
     7 import org.springframework.web.bind.annotation.PostMapping;
     8 import org.springframework.web.bind.annotation.RequestBody;
     9 
    10 /**
    11  * @author : Jixiaohu
    12  * @Date : 2019-04-12.
    13  * @Time : 16:50.
    14  * @Description :
    15  */
    16 @FeignClient(name = "microservice-provider-user", fallbackFactory =
    17     UserFeginClientFactory.class)
    18 public interface UserFeignClient {
    19     //@PathVariable得设置value
    20     @GetMapping("/simple/{id}")
    21     User findById(@PathVariable("id") Long id); //@PathVariable得设置value
    22 }

     启动user服务,movie服务,先正常访问:

    然后关闭user服务,会发现控制台开始打印日志:

    这是为什么呢?因为此时,断路器并没有打开,实际的原因是TimeoutException

    当断路器打开时,就会答应异常的信息。

  • 相关阅读:
    题解 P5996 【[PA2014]Muzeum】
    题解 CF1433G 【Reducing Delivery Cost】
    题解 CF1430E 【String Reversal】
    题解 CF710F 【String Set Queries】
    题解 P4334 【[COI2007] Policija】
    LIS 树状数组优化
    离散化模板
    P4309 [TJOI2013]最长上升子序列
    p3902 递增(incr)
    poj3417 暗的连锁
  • 原文地址:https://www.cnblogs.com/shmilyToHu/p/10725944.html
Copyright © 2011-2022 走看看