一个线上问题的思考:Eureka注册中心集群如何实现客户端请求负载及故障转移? (3)

负载测试结果如下:

负载测试结果.png

可以看到第二个机器会有50%的请求,最后一台机器只有17%的请求,负载的情况并不是很均匀,我认为通过IP负载并不是一个好的方案。

还记得我们之前讲过Ribbon默认的轮询算法RoundRobinRule,【一起学源码-微服务】Ribbon 源码四:进一步探究Ribbon的IRule和IPing 。

这种算法就是一个很好的散列算法,可以保证每次请求都很均匀,原理如下图:

Ribbon轮询算法.png

故障转移原理 原理图解

还是先上结论,如下图:

故障转移原理.png

我们的serverList按照client端的ip进行重排序后,每次都会请求第一个元素作为和Server端交互的host,如果请求失败,会尝试请求serverList列表中的第二个元素继续请求,这次请求成功后,会将此次请求的host放到全局的一个变量中保存起来,下次client端再次请求 就会直接使用这个host。

这里最多会重试请求两次。

代码实现

直接看底层交互的代码,位置在
com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute() 中:

重试代码.png

我们来分析下这个代码:

第101行,获取client上次成功server端的host,如果有值则直接使用这个host

第105行,getHostCandidates()是获取client端配置的serverList数据,且通过ip进行重排序的列表

第114行,candidateHosts.get(endpointIdx++),初始endpointIdx=0,获取列表中第1个元素作为host请求

第120行,获取返回的response结果,如果返回的状态码是200,则将此次请求的host设置到全局的delegate变量中

第133行,执行到这里说明第120行执行的response返回的状态码不是200,也就是执行失败,将全局变量delegate中的数据清空

再次循环第一步,此时endpointIdx=1,获取列表中的第二个元素作为host请求

依次执行,第100行的循环条件numberOfRetries=3,最多重试2次就会跳出循环

我们还可以第123和129行,这也正是我们业务抛出来的日志信息,所有的一切都对应上了。

总结

感谢你看到这里,相信你已经清楚了开头提问的问题。

上面已经分析完了Eureka集群下Client端请求时负载均衡的选择以及集群故障时自动重试请求的实现原理。

如果还有不懂的问题,可以添加我的微信或者给我公众号留言,我会单独和你讨论交流。

本文首发自:一枝花算不算浪漫 公众号,如若转载请在文章开头标明出处,如需开白可直接公众号回复即可。

原创干货分享.png


原创干货分享.png

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwwjz.html