1.远程调用
我们知道微服务间远程调用都是有OpenFeign帮我们完成的,甚至帮我们实现了服务列表之间的负载均衡。但具体负载均衡的规则是什么呢?何时做的负载均衡呢?
接下来我们一起来分析一下。
1.1.负载均衡原理
在SpringCloud的早期版本中,负载均衡都是有Netflix公司开源的Ribbon组件来实现的,甚至Ribbon被直接集成到了Eureka-client和Nacos-Discovery中。
但是自SpringCloud2020版本开始,已经弃用Ribbon,改用Spring自己开源的Spring Cloud LoadBalancer了,我们使用的OpenFeign的也已经与其整合。
接下来我们就通过源码分析,来看看OpenFeign底层是如何实现负载均衡功能的。
1.1.1.源码跟踪
要弄清楚OpenFeign的负载均衡原理,最佳的办法肯定是从FeignClient的请求流程入手。
⁉️ 首先,我们在com.hmall.cart.service.impl.CartServiceImpl
中的queryMyCarts
方法中打一个断点。然后在swagger页面请求购物车列表接口。
进入断点后,观察ItemClient
这个接口:
你会发现ItemClient是一个代理对象,而代理的处理器则是SentinelInvocationHandler
。这是因为我们项目中引入了Sentinel
导致。
我们进入SentinelInvocationHandler
类中的invoke
方法看看:
可以看到这里是先获取被代理的方法的处理器MethodHandler
,接着,Sentinel就会开启对簇点资源的监控:
开启Sentinel的簇点资源监控后,就可以调用处理器了,我们尝试跟入,会发现有两种实现:
这其实就是OpenFeign远程调用的处理器了。继续跟入会进入SynchronousMethodHandler
这个实现类:
在上述方法中,会循环尝试调用executeAndDecode()
方法,直到成功或者是重试次数达到Retryer中配置的上限。
我们继续跟入executeAndDecode()
方法:
executeAndDecode()
方法最终会利用client
去调用execute()
方法,发起远程调用。
这里的client的类型是feign.Client
接口,其下有很多实现类:
由于我们项目中整合了seata,所以这里client对象的类型是SeataFeignBlockingLoadBalancerClient
,内部实现如下:
这里直接调用了其父类,也就是FeignBlockingLoadBalancerClient
的execute
方法,来看一下: