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
隔舱原理