Spring Cloud Feign原理

  • Feign运行过程
  • 重试机制
  • 服务降级
  • 负载均衡
  • 隔舱原理


Feign运行过程

  • 通过主类上的EnableFeignClients 注解开启FeignClient;
  • 根据Feign 的规则实现接口,并加上FeignClient注解,供调用的地方注入调用;
  • 程序启动后,会扫描所有FeignClient 注解的类,并将这些信息注入到IOC 容器中;
  • 当b中接口被调用时,通过jdk代理,以及反射(Spring处理注解的方式),来生成具体的RequestTemplate
  • RequestTemplate 生成Reqest
  • Request 交给httpclient处理,这里的httpclient 可以是OkHttp,也可以是HttpUrlConnection 或者HttpClient
  • 最后Client被封装到LoadBalanceClient类,这个类结合Ribbon 实现负载均衡

重试机制

在 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";
}

服务降级

服务熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务不可用或者响应时间太长,就会进行服务的降级,快速熔断该节点微服务的调用,返回默认的响应信息。当检测到该节点微服务调用响应正常后即可恢复。

上面提到服务的降级,什么意思呢?我打个比方:比如你去银行办理业务,本来有四个窗口都可以办理,现在3号窗口和4号窗口的办理人员有事要离开,那么自然地,用户就会跑去1号窗口或者2号窗口办理,所以1号和2号窗口就会承担更多的压力。

3号窗口和4号窗口的人有事走了,不能让人还在这排队等着吧,否则就出现了上文说的雪崩了,所以会挂一个牌子:暂停服务。这个牌子好比上文提到的熔断,然后返回一个默认的信息,让用户知道。等3号和4号窗口的人回来了,就会把这个牌子拿走,这两个窗口又可以继续回复服务了。

服务降级是在客户端完成的,不是服务端,与服务端是没有关系的。就像银行某个窗口挂了“暂停服务”,那客户会自然去别的窗口。

负载均衡

以上就是 Feign 的使用,很简单,也符合我们平时的接口调用习惯。但是这是默认的轮询负载均衡算法。在上一节我们知道,Ribbon 中支持很多自带的均衡算法,我们只要在代码中根据具体情况,选择合适的均衡算法即可。甚至我们可以选择自己自定义的均衡算法。

那么使用 Feign 的时候,如何去切换到 Ribbon 中其他均衡策略呢?甚至切换到自定义的策略呢?

也很简单,我们可以在 application.yml 配置文件中来指定,如下:

# feign和ribbon结合,指定策略。feign默认的是轮询的策略,这里的配置可以自定义
MICROSERVICE-ORDER:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

隔舱原理