spring_cloud_feign_ribbon_hystrix源码分析

流程图

openfeign流程图

@EnableFeignClients开启Feign功能

使用时都是在spring boot 启动类加上@EnableFeignClients注解。

1
2
3
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
}

注解上有FeignClientsRegistrar类

FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口

spring 启动时会调用registerBeanDefinitions方法

1
2
3
4
5
6
7
8
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//注册@EnableFeignClients上定义的defaultConfiguration默认配置类
registerDefaultConfiguration(metadata, registry);
//扫描所有的@FeignClient注解
registerFeignClients(metadata, registry);
}

注册默认配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#FeignClientsRegistrar
private void registerDefaultConfiguration(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//获取@EnableFeignClients配置的信息
Map<String, Object> defaultAttrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
//判断是否配置了defaultConfiguration
if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
String name;
//判断配置在defaultConfiguration是否为内部类,拼接对应的类名
if (metadata.hasEnclosingClass()) {
name = "default." + metadata.getEnclosingClassName();
}
else {
name = "default." + metadata.getClassName();
}
//跟进去
registerClientConfiguration(registry, name,
defaultAttrs.get("defaultConfiguration"));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
#FeignClientsRegistrar
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
Object configuration) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientSpecification.class);
builder.addConstructorArgValue(name);
builder.addConstructorArgValue(configuration);
//将@EnableFeignClients中的配置信息注册到容器中
registry.registerBeanDefinition(
name + "." + FeignClientSpecification.class.getSimpleName(),
builder.getBeanDefinition());
}

扫描@FeignClient注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#FeignClientsRegistrar
public void registerFeignClients(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//获取类路径扫描器
ClassPathScanningCandidateComponentProvider scanner = getScanner();
//设置资源加载器
scanner.setResourceLoader(this.resourceLoader);
Set<String> basePackages;
//获取@EnableFeignClients的注解信息
Map<String, Object> attrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName());
//创建@FeignClient类型的过滤器
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
FeignClient.class);
final Class<?>[] clients = attrs == null ? null
: (Class<?>[]) attrs.get("clients");
if (clients == null || clients.length == 0) {
scanner.addIncludeFilter(annotationTypeFilter);
//获取包路径
basePackages = getBasePackages(metadata);
}
else {
for (Class<?> clazz : clients) {
candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
}
}
//遍历包路径
for (String basePackage : basePackages) {
//获取该包路径下带@FeignClient的BD信息
Set<BeanDefinition> candidateComponents = scanner
.findCandidateComponents(basePackage);
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(),
"@FeignClient can only be specified on an interface");
//获取@FeignClient的注解信息
Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(
FeignClient.class.getCanonicalName());
//获取@FeignClient上配置的名称,优先级为contextId>value>name>serviceId
String name = getClientName(attributes);
//注册@FeignClient的配置信息
registerClientConfiguration(registry, name,
attributes.get("configuration"));
//注册加了@FeignClient的类到容器中
registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#FeignClientsRegistrar
private void registerFeignClient(BeanDefinitionRegistry registry,
AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
//返回添加了@FeignClient注解的Class的全限定名, 包名.类名
String className = annotationMetadata.getClassName();
//FeignClientFactoryBean是一个FactoryBean,用它来创建具体的FeignClient
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
validate(attributes);
//向FeignClientFactoryBean添加@FeignClient中配置的一些注解信息
definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("path", getPath(attributes));
String name = getName(attributes);
definition.addPropertyValue("name", name);
String contextId = getContextId(attributes);
definition.addPropertyValue("contextId", contextId);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
String alias = contextId + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
boolean primary = (Boolean) attributes.get("primary");
beanDefinition.setPrimary(primary);
String qualifier = getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
new String[] { alias });
//将FeignClientFactoryBean注册到容器中
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}

这一步完成后,所有的加了@FeignClient的类就会被解析成FeignClientFactoryBean类型的BeanDefinition加入到容器中,FeignClientFactoryBean包含了@FeignClient上配置的信息,以及保存了当前添加@FeignClient注解的Class名称。之后就是Spring容器在refresh()内会去实例化该FeignClient,而FeignClientFactoryBean是FactoryBean类型,所以会调用它的getObject()进行实例化。

FeignClient实例化

1
2
3
4
#FeignClientFactoryBean
public Object getObject() throws Exception {
return getTarget();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#FeignClientFactoryBean
<T> T getTarget() {
//获取FeignContext,在FeignAutoConfiguration自动装配进来
FeignContext context = this.applicationContext.getBean(FeignContext.class);
//创建builder对象,用来生成Feign
Feign.Builder builder = feign(context);
//如果没有在@FeignClient配置了url,说明要负载均衡
if (!StringUtils.hasText(this.url)) {
//构造url
if (!this.name.startsWith("http")) {
this.url = "http://" + this.name;
}
else {
this.url = this.name;
}
//http://服务名
this.url += cleanPath();
//创建负载均衡代理类
return (T) loadBalance(builder, context,
new HardCodedTarget<>(this.type, this.name, this.url));
}

//说明url存在,使用硬编码的方式
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
//直接拼接url
this.url = "http://" + this.url;
}
String url = this.url + cleanPath();
//获取客户端对象
Client client = getOptional(context, Client.class);
if (client != null) {
//Ribbon客户端对象LoadBalancerFeignClient
if (client instanceof LoadBalancerFeignClient) {
client = ((LoadBalancerFeignClient) client).getDelegate();
}
builder.client(client);
}
//在FeignAutoConfiguration自动装配进来
Targeter targeter = get(context, Targeter.class);
//生成动态代理对象
return (T) targeter.target(this, builder, context,
new HardCodedTarget<>(this.type, this.name, url));
}

FeignContext在哪注入到spring容器的呢?在FeignAutoConfiguration中

FeignAutoConfiguration自动装配

1
spring-cloud-starter-openfeign pom.xml  -> spring-cloud-openfeign-core -> spring.factories -> org.springframework.cloud.openfeign.FeignAutoConfiguration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Configuration
@ConditionalOnClass(Feign.class)
@EnableConfigurationProperties({ FeignClientProperties.class,
FeignHttpClientProperties.class })
public class FeignAutoConfiguration {

//FeignContext,内部保存了创建FeignClient所需的组件
@Bean
public FeignContext feignContext() {
FeignContext context = new FeignContext();
context.setConfigurations(this.configurations);
return context;
}

//以下是两个相对的条件
@Configuration
@ConditionalOnClass(name = "feign.hystrix.HystrixFeign")//引入hystrix
protected static class HystrixFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
//创建Hystrix类型
return new HystrixTargeter();
}
}

@Configuration
@ConditionalOnMissingClass("feign.hystrix.HystrixFeign")//未引入hystrix
protected static class DefaultFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
//创建默认类型
return new DefaultTargeter();
}

}

//下面还有HttpClient,Okhttp的配置
}

FeignAutoConfiguration配置类会自动装配一些用来创建FeignClient实例的Bean信息。

创建生成Feign的Builder对象

1
2
3
#FeignClientFactoryBean#getTarget() 
//创建builder对象,用来生成Feign
Feign.Builder builder = feign(context);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#FeignClientFactoryBean
protected Feign.Builder feign(FeignContext context) {
FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);
Logger logger = loggerFactory.create(this.type);
//设置Logger、Encoder、Decoder等组件
Feign.Builder builder = get(context, Feign.Builder.class)
.logger(logger)
.encoder(get(context, Encoder.class))
.decoder(get(context, Decoder.class))
.contract(get(context, Contract.class));
//配置builder
configureFeign(context, builder);
return builder;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#FeignClientFactoryBean
protected void configureFeign(FeignContext context, Feign.Builder builder) {
FeignClientProperties properties = this.applicationContext
.getBean(FeignClientProperties.class);
//从.properties配置文件中加载配置
if (properties != null) {
if (properties.isDefaultToProperties()) {
configureUsingConfiguration(context, builder);
configureUsingProperties(
properties.getConfig().get(properties.getDefaultConfig()),
builder);
configureUsingProperties(properties.getConfig().get(this.contextId),
builder);
}
else {
configureUsingProperties(
properties.getConfig().get(properties.getDefaultConfig()),
builder);
configureUsingProperties(properties.getConfig().get(this.contextId),
builder);
configureUsingConfiguration(context, builder);
}
}
//配置类@Bean加载配置
else {
configureUsingConfiguration(context, builder);
}
}

在加载配置到builder对象中后,就是去生成代理对象的逻辑。

创建Feign代理对象

首先来看看创建负载均衡代理对象

1
2
3
4
#FeignClientFactoryBean#getTarget() 
//创建负载均衡代理类
return (T) loadBalance(builder, context,
new HardCodedTarget<>(this.type, this.name, this.url));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#FeignClientFactoryBean
protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
HardCodedTarget<T> target) {
//获取客户端对象
Client client = getOptional(context, Client.class);
if (client != null) {
builder.client(client);
//获取Targeter,分别有HystrixTargeter和DefaultTargeter类型
Targeter targeter = get(context, Targeter.class);
//创建代理对象,跟进去,是一个接口方法,分别对应上面两种类型的实现
return targeter.target(this, builder, context, target);
}
throw new IllegalStateException(
"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
}

DefaultTargeter创建代理对象

1
2
3
4
5
#FeignClientFactoryBean
//获取Targeter,分别有HystrixTargeter和DefaultTargeter类型
Targeter targeter = get(context, Targeter.class);
//创建代理对象,跟进去,是一个接口方法,分别对应上面两种类型的实现
return targeter.target(this, builder, context, target);
1
2
3
4
5
#DefaultTargeter
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign,
FeignContext context, Target.HardCodedTarget<T> target) {
return feign.target(target);
}
1
2
3
4
5
#Feign
public <T> T target(Target<T> target) {
//跟进去
return build().newInstance(target);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
#Feign.Builder
public Feign build() {
//构建SynchronousMethodHandler工厂
SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
logLevel, decode404, closeAfterDecode, propagationPolicy);
//设置组件对象
ParseHandlersByName handlersByName =
new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder,
errorDecoder, synchronousMethodHandlerFactory);
//创建ReflectiveFeign实例,invocationHandlerFactory是InvocationHandlerFactory.Default类型
return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ReflectiveFeign  是Feign的实现类
public <T> T newInstance(Target<T> target) {
//target内部保存了当前加了@FeignClient的接口Class,apply()会解析出接口中的方法和方法上的注解
//key是方法名,value是SynchronousMethodHandler类型,内部持有这个方法和注解的所有信息
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
//target.type()就是获取接口的Class
//遍历所有的接口方法
for (Method method : target.type().getMethods()) {
if (method.getDeclaringClass() == Object.class) {
//Object的方法不管
continue;
} else if (Util.isDefault(method)) {
//default 类型的方法,要加入到defaultMethodHandlers集合
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
//非Object,default的方法,从nameToHandler中取出添加到methodToHandler集合
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
//InvocationHandler工厂创建InvocationHandler对象
InvocationHandler handler = factory.create(target, methodToHandler);
//创建代理对象
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
new Class<?>[] {target.type()}, handler);
for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
//将default方法绑定在代理对象上
defaultMethodHandler.bindTo(proxy);
}
//返回代理对象
return proxy;
}

InvocationHandler对象调用invoke()

1
2
3
4
5
#InvocationHandlerFactory.Default
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
//创建了FeignInvocationHandler类型的InvocationHandler,直接看它的invoke方法
return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);
}

当feignClient中的方法被调用后会执行FeignInvocationHandler的invoke方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#FeignInvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("equals".equals(method.getName())) {
try {
Object otherHandler =
args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
return equals(otherHandler);
} catch (IllegalArgumentException e) {
return false;
}
} else if ("hashCode".equals(method.getName())) {
return hashCode();
} else if ("toString".equals(method.getName())) {
return toString();
}
//dispatch就是在构造中赋值的,在#ReflectiveFeign的newInstance()方法中的methodToHandler
//key为接口中的方法,value为SynchronousMethodHandler和DefaultMethodHandler类型
//所以接下来就去看这两个类型的invoke方法
return dispatch.get(method).invoke(args);
}
DefaultMethodHandler的invoke()
1
2
3
4
5
6
7
8
public Object invoke(Object[] argv) throws Throwable {
if (handle == null) {
throw new IllegalStateException(
"Default method handler invoked before proxy has been bound.");
}
//default修饰的方法就直接执行
return handle.invokeWithArguments(argv);
}
SynchronousMethodHandler的invoke()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public Object invoke(Object[] argv) throws Throwable {
//将方法参数构建成RequestTemplate,这个对象相信大家都很熟悉
RequestTemplate template = buildTemplateFromArgs.create(argv);
Options options = findOptions(argv);
Retryer retryer = this.retryer.clone();
while (true) {
try {
//执行请求
return executeAndDecode(template, options);
} catch (RetryableException e) {
try {
//重试机制
retryer.continueOrPropagate(e);
}
//......
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#SynchronousMethodHandler
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
//调用RequestInterceptor,根据template生成Request对象
Request request = targetRequest(template);
//......
//响应对象
Response response;
long start = System.nanoTime();
try {
//调用客户端的execute执行请求
response = client.execute(request, options);
} catch (IOException e) {
//......
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
boolean shouldClose = true;
try {
//......
//对response进行解码
if (Response.class == metadata.returnType()) {
if (response.body() == null) {
return response;
}
if (response.body().length() == null ||
response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {
shouldClose = false;
return response;
}
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
return response.toBuilder().body(bodyData).build();
}
if (response.status() >= 200 && response.status() < 300) {
if (void.class == metadata.returnType()) {
return null;
} else {
Object result = decode(response);
shouldClose = closeAfterDecode;
return result;
}
} else if (decode404 && response.status() == 404 && void.class != metadata.returnType()) {
Object result = decode(response);
shouldClose = closeAfterDecode;
return result;
} else {
throw errorDecoder.decode(metadata.configKey(), response);
}
}
//......
}

真正执行请求的client.execute(request, options)是一个接口方法,是由不同的客户端工具进行实现。如果没有导入Ribbon,那么就用feign自带的Client.Default内部进行实现。Client是一个接口。

1
2
3
4
5
6
7
#Client.Default
public Response execute(Request request, Options options) throws IOException {
//convertAndSend()发送请求
HttpURLConnection connection = convertAndSend(request, options);
//convertResponse()响应解码
return convertResponse(connection, request);
}

如果导入了Ribbon,那么就是LoadBalancerFeignClient实现,内部使用Ribbon进行负载均衡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#LoadBalancerFeignClient
public Response execute(Request request, Request.Options options) throws IOException {
try {
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutHost = cleanUrl(request.url(), clientName);
FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
this.delegate, request, uriWithoutHost);
IClientConfig requestConfig = getClientConfig(options, clientName);
return lbClient(clientName)
.executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
}
//......
}

到这里,没有导入Hystrix创建代理对象的流程就分析完了,一些具体解析的方法并没有去详细分析,因为我们主要是理解openfeign的执行流程,所以分析创建代理对象,然后到真正执行请求的地方就行了。接下来是去分析引入了Hystrix后是如何创建代理。

HystrixTargeter创建代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#HystrixTargeter
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign,
FeignContext context, Target.HardCodedTarget<T> target) {
//判断是否为HystrixFeign类型
if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
//这里会调用ReflectiveFeign的那段逻辑
return feign.target(target);
}
feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
String name = StringUtils.isEmpty(factory.getContextId()) ? factory.getName()
: factory.getContextId();
SetterFactory setterFactory = getOptional(name, context, SetterFactory.class);
if (setterFactory != null) {
builder.setterFactory(setterFactory);
}
//是否设置降级
Class<?> fallback = factory.getFallback();
if (fallback != void.class) {
return targetWithFallback(name, context, target, builder, fallback);
}
Class<?> fallbackFactory = factory.getFallbackFactory();
if (fallbackFactory != void.class) {
return targetWithFallbackFactory(name, context, target, builder,
fallbackFactory);
}
//执行到这说明没有设置降级,又会回到ReflectiveFeign
return feign.target(target);
}

虽然导入了Hystrix,但是内部还是会判断是否设置过降级,如果没有,会回到普通的调用链路。上面的降级分支最终都会合并到一起,所以分析一个方法就行。

1
2
3
4
5
6
7
8
9
#HystrixTargeter
private <T> T targetWithFallback(String feignClientName, FeignContext context,
Target.HardCodedTarget<T> target, HystrixFeign.Builder builder,
Class<?> fallback) {
T fallbackInstance = getFromContext("fallback", feignClientName, context,
fallback, target.type());
//创建代理对象,跟进去
return builder.target(target, fallbackInstance);
}
1
2
3
4
5
6
7
#HystrixFeign.Builder
public <T> T target(Target<T> target, T fallback) {
//newInstance会回到ReflectiveFeign逻辑,我们关心的是引入hystrix后,InvocationHandler的类型
//在build中会设置InvocationHandlerFactory的类型
return build(fallback != null ? new FallbackFactory.Default<T>(fallback) : null)
.newInstance(target);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#HystrixFeign.Builder
Feign build(final FallbackFactory<?> nullableFallbackFactory) {
super.invocationHandlerFactory(new InvocationHandlerFactory() {
@Override
public InvocationHandler create(Target target,
Map<Method, MethodHandler> dispatch) {
//最终返回了HystrixInvocationHandler实例,所以去看它的invoke方法
return new HystrixInvocationHandler(target, dispatch, setterFactory,
nullableFallbackFactory);
}
});
super.contract(new HystrixDelegatingContract(contract));
return super.build();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#HystrixInvocationHandler
public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable {
//......
HystrixCommand<Object> hystrixCommand =
new HystrixCommand<Object>(setterMethodMap.get(method)){
@Override
protected Object run() throws Exception {
try {
//在这里回到SynchronousMethodHandler和DefaultMethodHandler的invoke逻辑
return HystrixInvocationHandler.this.dispatch.get(method).invoke(args);
} catch (Exception e) {
throw e;
} catch (Throwable t) {
throw (Error) t;
}
}
//......
};
//最终调用到Hystrix处理逻辑
return hystrixCommand.execute();
}

到这里Hystrix的代理逻辑也分析完了,它和默认创建代理对象的逻辑就是invoke()的实现不同,它只是对请求加了熔断降级的处理,其他的流程基本一致。

以上就是openfeign源码分析的整体流程,首先从feign的功能是如何开启的开始分析,然后到FeignClient是如何添加到容器当中,接着分析FeignClient是如何被代理创建,最后分析了默认方式和引入Hystrix的方式分别是如何执行的。

hystrix配置

1
2
3
4
protected HystrixCommand(Setter setter) {
// use 'null' to specify use the default
this(setter.groupKey, setter.commandKey, setter.threadPoolKey, null, null, setter.commandPropertiesDefaults, setter.threadPoolPropertiesDefaults, null, null, null, null, null);
}

发现commandPropertiesDefaults 和 threadPoolPropertiesDefaults

commandPropertiesDefaults 是命令相关参数、断路器相关参数

threadPoolPropertiesDefaults 是线程池相关参数

ribbon源码

1
2
3
4
5
6
7
#HystrixInvocationHandler# invoke方法
return HystrixInvocationHandler.this.dispatch.get(method).invoke(args);
# SynchronousMethodHandler
return executeAndDecode(template, options);
#SynchronousMethodHandler
response = client.execute(request, options);
# 这时要看是哪个client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#LoadBalancerFeignClient
@Override
public Response execute(Request request, Request.Options options) throws IOException {
try {
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutHost = cleanUrl(request.url(), clientName);
FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
this.delegate, request, uriWithoutHost);

IClientConfig requestConfig = getClientConfig(options, clientName);
return lbClient(clientName)
.executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
}
catch (ClientException e) {
IOException io = findIOException(e);
if (io != null) {
throw io;
}
throw new RuntimeException(e);
}
}

1
2
#AbstractLoadBalancerAwareClient
public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig)
1
2
3
4
5
6
#AbstractLoadBalancerAwareClient
LoadBalancerCommand<T> command = buildLoadBalancerCommand(request, requestConfig);
return command.submit(....)
#LoadBalancerCommand
Observable<T> o =
(server == null ? selectServer() : Observable.just(server))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#LoadBalancerCommand
private Observable<Server> selectServer() {
return Observable.create(new OnSubscribe<Server>() {
@Override
public void call(Subscriber<? super Server> next) {
try {
Server server = loadBalancerContext.getServerFromLoadBalancer(loadBalancerURI, loadBalancerKey);
next.onNext(server);
next.onCompleted();
} catch (Exception e) {
next.onError(e);
}
}
});
}
1
2
3
4
#LoadBalancerCommand
Server server = loadBalancerContext.getServerFromLoadBalancer(loadBalancerURI, loadBalancerKey);
#LoadBalancerContext
Server svc = lb.chooseServer(loadBalancerKey);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Server chooseServer(Object key) {
if (counter == null) {
counter = createCounter();
}
counter.increment();
if (rule == null) {
return null;
} else {
try {
return rule.choose(key);
} catch (Exception e) {
logger.warn("LoadBalancer [{}]: Error choosing server for key {}", name, key, e);
return null;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
IRule (com.netflix.loadbalancer)
AbstractLoadBalancerRule (com.netflix.loadbalancer)
ClientConfigEnabledRoundRobinRule (com.netflix.loadbalancer)
BestAvailableRule (com.netflix.loadbalancer)
PredicateBasedRule (com.netflix.loadbalancer)
ZoneAvoidanceRule (com.netflix.loadbalancer)
AvailabilityFilteringRule (com.netflix.loadbalancer)
RoundRobinRule (com.netflix.loadbalancer)
WeightedResponseTimeRule (com.netflix.loadbalancer)
ResponseTimeWeightedRule (com.netflix.loadbalancer)
RandomRule (com.netflix.loadbalancer)
RetryRule (com.netflix.loadbalancer)

ZoneAvoidanceRule(区域权衡策略):复合判断Server所在区域的性能和Server的可用性,轮询选择服务器。

其他规则:

BestAvailableRule(最低并发策略):会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。逐个找服务,如果断路器打开,则忽略。

RoundRobinRule(轮询策略):以简单轮询选择一个服务器。按顺序循环选择一个server。

RandomRule(随机策略):随机选择一个服务器。

AvailabilityFilteringRule(可用过滤策略):会先过滤掉多次访问故障而处于断路器跳闸状态的服务和过滤并发的连接数量超过阀值得服务,然后对剩余的服务列表安装轮询策略进行访问。

WeightedResponseTimeRule(响应时间加权策略):据平均响应时间计算所有的服务的权重,响应时间越快服务权重越大,容易被选中的概率就越高。刚启动时,如果统计信息不中,则使用RoundRobinRule(轮询)策略,等统计的信息足够了会自动的切换到WeightedResponseTimeRule。响应时间长,权重低,被选择的概率低。反之,同样道理。此策略综合了各种因素(网络,磁盘,IO等),这些因素直接影响响应时间。

RetryRule(重试策略):先按照RoundRobinRule(轮询)的策略获取服务,如果获取的服务失败则在指定的时间会进行重试,进行获取可用的服务。如多次获取某个服务失败,就不会再次获取该服务。主要是在一个时间段内,如果选择一个服务不成功,就继续找可用的服务,直到超时。


spring_cloud_feign_ribbon_hystrix源码分析
http://hanqichuan.com/2022/06/14/spring_cloud/spring_cloud_feign_ribbon_hystrix源码分析/
作者
韩启川
发布于
2022年6月14日
许可协议