openFeign 源码解析
2021-09-08 03:45:19 5 举报
OpenFeign是一个声明式的Web Service客户端,它使得编写HTTP客户端变得更简单。我们只需要使用注解方式来编写HTTP请求,再通过Feign自身提供的解码器将请求结果转换为Java对象即可,而无需考虑底层的实现细节。 OpenFeign支持负载均衡和断路器功能,在发生故障时会自动切换到其他服务节点,保证系统的高可用性。同时,它还支持Hystrix的熔断机制,可以在服务超时或异常时快速失败,防止系统崩溃。 总之,OpenFeign是一个非常实用的工具,可以大大提高开发效率和系统的稳定性。
作者其他创作
大纲/内容
com.qmy.feign.UserFeignClient
server
implements
return request
2、执行 submit
target 是HardodeTarget
URI.create(request.url())
2、执行真是逻辑
实现 feign 接口的代理逻辑的调用处理器
将 @FeignClient 修饰的接口封装为 BeanDefinition,注册进Spring容器
封装 response 并返回
spring.factoies
用户访问
getObject()
例如:default.com.qmy.MainApplication.FeignClientSpecification
path
resolved.body(this.body.expand(variables));
1、创建一个 restTemplate
默认 Feign.builder().retryer(retryer),整合 Hystrix 后,HystrixFeign.builder()
url
interceptor.apply(template);
2、获取需要请求的微服务应用名
fallback
获取 loadBalanceFeignClient,用于 feign 调用
2、
3、对原有的 request 进行封装,封装为具有 ribbon 负载均衡功能的 request请求
registerBeanDefinitions
http://{name}/{path}
@Override
return template
@FeiClient(name=\"user-provider\")eg:user-provider
获取代理对象
String clientName = asUri.getHost()
解析 @EnableFeignClients 注解属性
call()
1、创建一个 LoadBalancerCommand
this.uriTemplate.expand(variables)
FeignClientsRegistrar
@FeignClient(name=\"user-provider\",url=\"http://localhost:8080/user\")
这个方法返回 url 地址eg: /provider/1
selectServer()
这里会循环调用实现了 RequestInterceptor 接口的实现类,执行它的 apply 方法,这个方法会将 restTemplate 传入,此时就可以给 restemplate 添加上用户请求携带的请求头信息,避免因使用 feign 远程调用而丢失请求头
ScalarSynchronousObservable.create(value)
uri.append(this.uriTemplate.expand(variables))
创建一个 restTemplate,并将参数与url解析绑定,argv即 url 中 基于 restful 的参数
根据 method 方法名获取一个SynchronousMethodHandler,然后调用其 invoke 方法
eg:com.qmy.feignclient.UserFeign
@Bean
1、获取一个 Feign 的负载均衡器
PropertyValue
name
@EnableFeignClients
lbClient(clientName)
把 url 中的微服务名解析为 ip,执行真实请求
准备一个 map ,存放 url 参数
GenericBeanDefiition
返回一个新的 request
创建 server
doCreateBean
input.request()
Feign.Builder builder = feign(context)
FeignContext
扫描
font color=\"#ff9800\
beanName
FeignClientFactoryBean
for 结束,接下来根据 刚得到的 map 创建一个 jdk 动态代理的调用处理器
this.applicationContext.getBean(FeignContext.class)
创建一个新的请求
对 feign 接口接口实现 jdk 动态代理
创建一个新的 request 请求,用于请求远程服务
默认连接超时时间和读取超时时间都是 1s
判断是否引入 className: feign.hystrix.HystrixFeign存在:HystrixTargeter不存在:DefaultTargeter
5、
根据元数据中的 basePackage 属性,找到需要扫描的包
返回回来的 bean
Targeter
2
for.requestInterceptors
client.method()
解析 @EnableFeignClients 属性,注册 FeignClientsSpecification 类的 BeanDefinition
返回一个刚创建的新的请求
LoadBalanceFeignClient
font color=\"#f44336\
getTarget()
buid()
feign.target(target)
basePackages = getBasePackages(metadata);
创建 Observable
注册 FeignClientSpecification 类型的bean,beanName 为default + classpath:package + ApplicationMain + FeignClientSpecification
url 为空,则默认使用 ribbon 代理
将返回的 template 作为参数传入
metadata.getAnnotationAttributes(font color=\"#ffeb3b\
@FeignClient 没有配置 url 属性,就返回有负载均衡功能的代理对象
return LoadBalancerCommand
FeignLoadBalancer # execute
for 结束
FeignClientsConfiguration
否
FeignAutoConfiguration
BeanDefinition 数据结构
SynchronousMethodHandler # targetRequest(template);
target.apply(template);
return FeignLoadBalancer
resolved.headers(Collections.emptyMap());
默认 Default整合 ribbon:LoadBalancerFeignClient
如果 url 不为空,指定了 url,则使用默认生成代理类的方式
type
build().newInstance(target)
将所有被 @FeignClient 注解修饰的接口存入map,key 为 method,value 为 SynchronousMethodHandler
for 循环
返回 LoadBalanceFeignClient
传入 server
Feign.Builder
server是否为空
this.lbClientFactory.create(clientName)
resolved.uri(uri.toString())
for
return
@FeignClient(name=\"user-provider\")
把 methodToHandler 赋值给 dispatch
SynchronousMethodHandler # executeAndDecode(template)
FeignLoadBalancer client = this.cache.get(clientName);
feign 发起远程调用
eg:/uer
扫描被 @FeignClient 修饰的接口
RequestTemplate template = buildTemplateFromArgs.create(argv)
LoadBalancerCommand
补全 url,将 UserServiceA/provider/1 补齐为http://UserServiceA/provider/1
1
4、获取请求配置
FactoryBean
command.submit
dispatch.get(method).invoke(args)
1、创建一个 URI
beanClass
选择 server
feign 接口的全限定名
有参构造,对 dispatch 赋值
将收集到 url 参数的varbuilder 传入
Client
return response
input.target(url())
SynchronousMethodHandler # invoke()
FeignInvocationHandler # invoke()
getObjectFromFactoryBean()
@Import
是
@FeignClient
ImportBeanDefinitionRegistrar
uri是 StringBuilder
指定 fallback 方法
Feign 接口对应的代理类
1、创建新的 request
0 条评论
下一页