SpringCloud详解 第四章声明式服务调用 Feign(二)

本章主要梳理Feign中Ribbon配置

一、全局配置

ribbon.ConnectTimeout = 500 //请求连接的超时时间。
ribbon.ReadTimeout = 2000  //请求处理的超时时间。

 

二、指定服务配置

大多数情况下,我们对于服务调用的超时时间可能会根据实际服务的特性做 一 些调整,所以仅仅依靠默认的全局配置是不行的。 在使用SpringCloud Feign的时候,针对各个服务客户端进行个性化配置的方式与使用SpringCloud Ribbon时的配置方式是 一 样的, 都采用<client>. ribbon.key=value 的格式进行 设置。在定义Feign客户端的时候, 我们使用了@FeignClient注解。 在初始化过程中,SpringCloud Feign会根据该注解的name属性或value属性指定的服务名, 自动创建一 个同名的Ribbon客户端。也就是说,在之前的示例中,使用@FeignClient(value= "cloud-provider")来创 建 Feign 客 户 端 的 时 候 , 同时也创建了一个 名为cloud-provider的Ribbon客户端。 既然如此, 我们就可以使用@FeignClient注解中的name或value属性值来设置对应的Ribbon参数, 比如:

cloud-provider.ribbon.ConnectTimeout = 500 //请求连接的超时时间。
cloud-provider.ribbon.ReadTimeout = 2000  //请求处理的超时时间。
cloud-provider.ribbon.OkToRetryOnAllOperations = true //对所有操作请求都进行重试。
cloud-provider.ribbon.MaxAutoRetriesNextServer = 2 //切换实例的重试次数。
cloud-provider.ribbon.MaxAutoRetries = 1 //对当前实例的重试次数。

或这样写

user-service:   # 注意这是提供某一服务系统的服务名称,仅对这一服务起作用,不能随意抒写
  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  # 修改ribbon中默认的轮询为随机(采用spring系统提供包)
    ConnectTimeout: 250 # Ribbon的连接超时时间
    ReadTimeout: 1000 # Ribbon的数据读取超时时间
    OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
    MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
    MaxAutoRetries: 1 # 对当前实例的重试次数

三、重试机制

在 Spring Cloud Feign 中默认实 现了 请 求 的重 试 机 制 , 而上面我 们对 于 cloud-provider 客户端的配置内容就是对于请求超时以及重试机制配置的详情.

  这里需要注意一 点, Ribbon的超时 与Hystrix的超时是两个概念。 为了让上述实现有效,我们需要 让Hystrix的超时时间大于Ribbon的超时时间, 否则Hystrix命令超时后, 该命令直接熔断, 重试机制就 没有任何意义了。

  要么设置 Hystrix 的超时时间比Ribbon大(hystrix.command.default.execution.isolation.thread. timeoutInMilliseconds = 5000),要么直接关闭 Hystrix 超时配置(feign.hystrix.enabled= false).配置的时候不提示没关系,配置上就有效果。

  如果不想全局关闭可以只针对服务进行关闭:@FeignClient(name="HELLO - SERVICE", configuration = DisableHystrixConfiguration.class)

  在 feign-server应用中增加上文中提到的重试配置参数。其中,由于 cloud-provider.ribbon.MaxAutoRetries 设置为 1, 所以重试策略先尝试访问首选实例 一 次, 失败后才更换实例访问, 而更换实例访问的次数通过 cloud-provider.ribbon.MaxAutoRetriesNextServer 参数 设置为 2, 所以会尝试更换两次实例进行重试。

  最后, 启动这些应用, 并尝试访问几次 http://localhost:9012/feign­/hello 接口。可以通过 cloud-provider 服务打印请求信息,修改对应/hello接口如下

public String hello(String id) throws InterruptedException {
        // 测试fegin 超时重试代码开始
        List<ServiceInstance> instances = client.getInstances("feign-server");
        //测试超时
        int sleepTime = new Random().nextInt(3000);
        System.out.println("sleepTime:" + sleepTime);
        Thread.sleep(sleepTime);
        System.out.println("/hello, host:" + instances.get(0).getHost() +
                instances.get(0).getServiceId());
        // 测试fegin 超时重试代码结束
         return  "Hello Eureka Provider1";
    }

然后控制台来查看重试的日志。

  从控制台输出中,我们可以看到这次访问的第 一 次请求延迟时间为 2088毫秒,由于超时时间设置为 2000 毫秒, Feign 客户端发起了重试,第二次请求的延迟为 1338 秒,没有超时 。Feign客户端在进行服务调用时, 虽然经历了一 次失败,但是通过重试机制, 最终还是获得了请求结果。所以, 对于 重试机制的实现, 对于构建高可用的 服务集群来说非常重要, 而 SpringCloud Feign也为其提供了足够的支持。

 四、Ribbon和 Feign的区别:

  • Ribbon添加maven依赖 spring-starter-ribbon    使用@RibbonClient(value="服务名称")    使用RestTemplate调用远程服务对应的方法。feign添加maven依赖 spring-starter-feign    服务提供方提供对外接口  调用方使用    在接口上使用    @FeignClient("指定服务名")
  • Ribbon和Feign都是用于调用其他服务的,不过方式不同。
  • 启动类使用的注解不同,Ribbon用的是@RibbonClient,Feign用的是@EnableFeignClients。
  • 服务的指定位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明。
  • 调用方式不同,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。
  • Feign则是在Ribbon的基础上进行了一次改进,采用接口的方式,将需要调用的其他服务的方法定义成抽象方法即可,不需要自己构建http请求。不过要注意的是抽象方法的注解、方法签名要和提供服务的方法完全一致。
posted @ 2020-10-02 22:55  跃小云  阅读(131)  评论(0编辑  收藏  举报