zoukankan      html  css  js  c++  java
  • SpringCloud开发学习总结(七)—— 声明式服务调用Feign(三)

    Feign中的Ribbon配置

      由于Spring Cloud Feign的客户端负载均衡是通过Spring Cloud Ribbon实现的,所以我们可以直接通过配置Ribbon客户端的方式来自定义各个服务客户端调用多个参数。

    • 全局配置

       全局配置的方法非常简单,直接使用ribbon.<key>=<value>的方式来设置ribbon的各项默认参数。例如,修改默认的客户端调用超时时间:

    #请求连接的超时时间
    ribbon.ConnectTimeout=500
    #请求处理的超时时间
    ribbon.ReadTimeout=2000
    • 指定服务配置

      大多数情况,我们对于服务的超时时间可能会不同的服务特性做一些调整,针对各个服务客户端进行个性化配置的方式与使用Spring Cloud Ribbon时的配置方式是一样的,都采用<client>.ribbon.key=value 的格式进行设置,其中<client>指的是 @FeignClient(value="HELLO-SERVICE")中的value值,在使用@FeignClient(value="HELLO-SERVICE")来创建Feign客户端的时候,同时也创建了一个名为HELLO-SERVICE的Ribbon客户端,具体配置如下:

    HELLO-SERVICE.ribbon.ConnectTimeout=500  
    HELLO-SERVICE.ribbon.ReadTimeout=2000
    HELLO-SERVICE.ribbon.OkToRetryOnAllOperations=true
    #最多重试服务器的个数 HELLO-SERVICE.ribbon.MaxAutoRetriesNextServer=2
    #每台服务器最多重试次数,首次调用除外 HELLO-SERVICE.ribbon.MaxAutoRetries=1
    • 重试机制

      在Spring Cloud Feign中默认实现了请求的重试机制,而上面标红的就是对HELLO-SERVICE客户端的配置内容就是对于请求超时以及重试机制的配置,我们可以通过修改之前的示例做一些验证。在hello-service应用的/hello接口实现中,增加一个随机延迟,比如:

     1 package com.server.provide.web;
     2 
     3 import java.util.List;
     4 import java.util.Random;
     5 
     6 import org.apache.catalina.servlet4preview.http.HttpServletRequest;
     7 import org.slf4j.Logger;
     8 import org.slf4j.LoggerFactory;
     9 import org.springframework.beans.factory.annotation.Autowired;
    10 import org.springframework.cloud.client.ServiceInstance;
    11 import org.springframework.cloud.client.discovery.DiscoveryClient;
    12 import org.springframework.cloud.client.serviceregistry.Registration;
    13 import org.springframework.web.bind.annotation.RequestBody;
    14 import org.springframework.web.bind.annotation.RequestHeader;
    15 import org.springframework.web.bind.annotation.RequestMapping;
    16 import org.springframework.web.bind.annotation.RequestParam;
    17 import org.springframework.web.bind.annotation.RestController;
    18 
    19 
    20 @RestController
    21 public class HelloController {
    22     @Autowired
    23     private Registration registration;       // 服务注册
    24     @Autowired
    25     private DiscoveryClient discoveryClient; // 服务发现客户端
    26     private static final Logger log = LoggerFactory.getLogger(HelloController.class);
    27     @RequestMapping("/hello")
    28     public String hello(HttpServletRequest request) throws Exception {
    29         //测试超时
    30         int sleepTime = new Random().nextInt(3000);
    31         log.info("sleepTime"+sleepTime);
    32         Thread.sleep(sleepTime);
    33         log.info(request.getRemoteAddr()+","+request.getLocalName()+","+registration.getServiceId()+","+serviceInstance().getServiceId()); 
    34         return "hello I am provider";
    35     }
    36     
    37     @RequestMapping("/hello1")
    38     public String hello(@RequestParam String name) {
    39         return "Hello "+name;
    40     }
    41     
    42     @RequestMapping("/hello2")
    43     public User hello(@RequestHeader String name,@RequestHeader Integer age) {
    44         return new User(name,age);
    45     }
    46     
    47     @RequestMapping("/hello3")
    48     public String hello(@RequestBody User user) {
    49         return "Hello "+user.getName()+","+user.getAge();
    50     }
    51     
    52     /**
    53      * 获取当前服务的服务实例
    54      *
    55      * @return ServiceInstance
    56      */
    57     public ServiceInstance serviceInstance() {
    58         List<ServiceInstance> list = discoveryClient.getInstances(registration.getServiceId());
    59         if (list != null && list.size() > 0) {
    60             return list.get(0);
    61         }
    62         return null;
    63     }
    64     
    65 }

      在feign-consumer应用中增加上文中提到的重试配置参数。其中HELLO-SERVICE.ribbon.MaxAutoRetries=1代表重试机制在失败一次后,先尝试访问第一次失败的实例一次,再次失败后才更换服务器访问,而更换服务访问的次数通过HELLO-SERVICE.ribbon.MaxAutoRetriesNextServer=2控制,代表会尝试更换两次服务进行重试。

      最后,启动这些应用,并尝试访问几次http://localhost:8092/feign-consumer接口。当请求发生超时的时候,我们在服务提供者的控制台中会获得如下内容输出(由于sleepTime的随机性,并不一定每次相同):

      

    Feign中的Hystrix配置

      在Spring Cloud Feign中,除了引入了用于客户端负载均衡的Spring Cloud Ribbon之外,还引入了服务保护与容错的工具 Hystrix。本节中,将详细介绍如何在使用Spring Cloud Feign时配置Hystrix属性以及如何实现服务降级。

    • 全局配置

      对于Hystrix的全局配置同Spring Cloud Ribbon的全局配置一样,直接使用它的默认配置前缀hystrix.command.default就可以进行设置,比如设置全局的超时时间:

    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000

      另外,在对Hystrix进行配置之前,我们需要确认feign.hystrix.enabled参数没有被设置为false,否则该参数设置会关闭Feign客户端的Hystrix支持。而对于我们之前测试重拾机制时,对于Hystrix的超时时间控制除了可以使用上面的配置来增加熔断超时时间,也可以通过feign.hystrix.enabled=false来关闭Hystrix功能,或者使用hystrix,command.default.execution.timeout.enable=false来关闭熔断功能。

    •  禁用Hystrix

      上面我们提到了,在Spring Cloud Fegn中,可以通过feign.hystrix.enabled=false来关闭Hystrix功能。如果不想全局的关闭Hystrix支持,而只想针对某个服务客户端关闭Hystrix支持时,需要通过使用@Scope("prototype")注解为指定的客户端配置Feign.Builder实例,详细实现步骤如下:

      构建一个关闭Hystrix的配置类

     1 @Configuration
     2 public class DisableHystrixConfiguration {
     3 
     4     @Bean
     5     @Scope("prototype")
     6     public Feign.Builder feignBuilder(){
     7         
     8         return Feign.builder();
     9     }
    10     
    11 }

      在HelloService的@FeignClient注解中,通过configuration参数引入上面实现的配置

     1 @FeignClient(name="feign-provide",configuration=DisableHystrixConfiguration.class)
     2 public interface HelloService {
     3     
     4     @RequestMapping(value="/hello")
     5     String hello();
     6     @RequestMapping(value="/hello1",method=RequestMethod.GET)
     7     String hello(@RequestParam("name") String name);
     8     @RequestMapping(value="/hello2",method=RequestMethod.GET)
     9     String hello(@RequestHeader("name") String name,@RequestHeader("age") Integer age);
    10     @RequestMapping(value="/hello3",method=RequestMethod.POST)
    11     String hello(@RequestBody User user);
    12     
    13 }
    • 指定命令配置

      配制方法也跟传统的Hystrix命令的参数配置相似,采用hystrix.command.<commandKey>作为前缀。而<commandKey>默认情况下会采用Feign客户端中的方法名作为标识,所以,针对上一节介绍的尝试机制中对/hello接口的熔断超时时间的配置可以通过其方法名作为<commandKey>来进行配置:

    hystrix.command.hello.execution.isolation.thread.timeoutInMilliseconds=5000
    • 服务降级配置

      Hystrix提供的服务降级是服务容错的重要功能,由于Spring Cloud Feign在定义服务客户端的时候与Spring Cloud Ribbon有很大差别,HystrixCommand定义被封装了起来,我们无法像之前介绍Spring Cloud Hystrix时,通过@HystrixCommand注解的fallback参数那样来制定具体的服务降级处理方法。但是,Spring Cloud Feign提供了另外一种简单的定义方式。

      服务降级逻辑的实现只需要为Feign客户端的定义接口编写一个具体的接口实现类。比如为HelloService接口实现一个服务降级类HelloServiceFallback,其中每个重写方法的实现逻辑都可以用来定义相应的服务降级逻辑:

     1 @Component
     2 public class HelloServiceFallback implements HelloService {
     3 
     4     @Override
     5     public String hello(String name) {
     6         // TODO Auto-generated method stub
     7         return "error";
     8     }
     9 
    10 
    11     @Override
    12     public String hello(User user) {
    13         // TODO Auto-generated method stub
    14         return "error";
    15     }
    16 
    17     @Override
    18     public String hello() {
    19         // TODO Auto-generated method stub
    20         return "error";
    21     }
    22 
    23     @Override
    24     public String hello(String name, Integer age) {
    25         // TODO Auto-generated method stub
    26         return "error";
    27     }
    28 
    29 }

      在服务接口HelloService中,通过@FeignClient注解的fallback属性来制定对应的服务降级实现类。

     1 @FeignClient(name="feign-provide",fallback=HelloServiceFallback.class) //configuration=DisableHystrixConfiguration.class,
     2 public interface HelloService {
     3     
     4     @RequestMapping(value="/hello")
     5     String hello();
     6     @RequestMapping(value="/hello1",method=RequestMethod.GET)
     7     String hello(@RequestParam("name") String name);
     8     @RequestMapping(value="/hello2",method=RequestMethod.GET)
     9     String hello(@RequestHeader("name") String name,@RequestHeader("age") Integer age);
    10     @RequestMapping(value="/hello3",method=RequestMethod.POST)
    11     String hello(@RequestBody User user);
    12     
    13 }
    • 测试验证

      我们启动服务注册中心和feign-consumer,但不启动feign-provide服务,发送GET请求到http://localhost:8092/feign-consumer2,由于没有启动feign-provide服务,会直接触发服务降级,得到下面输出:


    注释一:Spring Cloud中提供的DiscoveryClient类,虽然有 
    ServiceInstance getLocalServiceInstance();方法,但是被标记为@Deprecated. 更为严重的是, Spring Cloud的Finchley版本中,getLocalServiceInstance方法从DiscoveryClient移除了,新版本中获取服务自身的ServiceInstance信息用registration.getServiceId()。

    注释二:在使用指定命令配置的时候,需要注意,由于方法名很有可能重复,这个时候相同方法名的Hystrix配置会共用,所以在进行方法定义与配置的时候需要做好一定的规则。当然,也可以重写Feign.Builder的实现,并在应用主类中创建它的实例来覆盖自动化配置的HystrixFeign.Builder实现。

    注释三:Feign对Hystrix的支持默认是关闭的,如果想开启对Hystrix的支持需要配置 feign.hystrix.enabled=true,并且需要把之前关闭Hystrix的配置类注释掉,方可开启服务降级功能,否则会报com.netflix.client.ClientException: Load balancer does not have available server for client:XXX

  • 相关阅读:
    MNIST手写字母识别(二)
    MNIST手写字母识别(一)
    多元线性回归问题(Tensorflow 求解)
    单变量线性回归问题(TensorFlow实战)
    TensorBoard可视化初步
    TensorFlow的基本运算
    NumPy科学计算库
    tensorflow使用Session模块时报错:AttributeError: module 'tensorflow' has no attribute 'Session',已解决
    Python 第一个爬虫
    Python(列表)
  • 原文地址:https://www.cnblogs.com/king-brook/p/9566613.html
Copyright © 2011-2022 走看看