前言
前情回顾
上一讲我们已经知道了Feign的工作原理其实是在项目启动的时候,通过JDK动态代理为每个FeignClinent生成一个动态代理。
动态代理的数据结构是:ReflectiveFeign.FeignInvocationHandler。其中包含target
(里面是serviceName等信息)和dispatcher
(map数据结构,key是请求的方法名,方法参数等,value是SynchronousMethodHandler
)。
如下图所示:
本讲目录
这一讲主要是Feign与Ribbon结合实现负载均衡的原理分析。
说明
原创不易,如若转载 请标明来源!
源码分析
Feign结合Ribbon实现负载均衡原理
通过前面的分析,我们可以直接来看下SynchronousMethodHandler
中的代码:
final class SynchronousMethodHandler implements MethodHandler {
@Override
public Object invoke(Object[] argv) throws Throwable {
// 生成请求类似于:GET /sayHello/wangmeng HTTP/1.1
RequestTemplate template = buildTemplateFromArgs.create(argv);
Retryer retryer = this.retryer.clone();
while (true) {
try {
return executeAndDecode(template);
} catch (RetryableException e) {
retryer.continueOrPropagate(e);
if (logLevel != Logger.Level.NONE) {
logger.logRetry(metadata.configKey(), logLevel);
}
continue;
}
}
}
Object executeAndDecode(RequestTemplate template) throws Throwable {
// 构建request对象:GET http://serviceA/sayHello/wangmeng HTTP/1.1
Request request = targetRequest(template);
if (logLevel != Logger.Level.NONE) {
logger.logRequest(metadata.configKey(), logLevel, request);
}
Response response;
long start = System.nanoTime();
try {
// 这个client就是之前构建的LoadBalancerFeignClient,options是超时时间
response = client.execute(request, options);
// ensure the request is set. TODO: remove in Feign 10
response.toBuilder().request(request).build();
} catch (IOException e) {
if (logLevel != Logger.Level.NONE) {
logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
}
throw errorExecuting(request, e);
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
// 下面逻辑都是构建返回值response
boolean shouldClose = true;
try {
if (logLevel != Logger.Level.