首先我要说的是springcloud没有rpc,这就涉及rpc和微服务的区别。springcloud的模块通信工具feign跟httpclient和okhttp是一样的东西,都是对http请求封装的工具,其实feign可以选择httpclient或者okhttp作为底层实现(修改配置即可)。

一、Feign的作用:

       ①封装http请求,使开发人员对发送请求的过程无感知,给人一种伪rpc感觉(这也许是feign这个名字的由来吧,伪装~)。

       ②feign整合ribbon和hystrix,结合eureka起到负载均衡和熔断器、降级作用。

二、源码及流程介绍:

我们从@EnableFeignClients这个注解开始追踪

Feign源码解析-LMLPHP

我们发现有个@Import注解,引用FeignClientRegistrar类,跟进去看看

Feign源码解析-LMLPHP

2个方法:①redisterDefalterConfiguration是加载配置,②registerFeignClients扫描你填写的basepackage下的所有@FeignClient注解的接口。第一个方法没啥好说的,我们主要看看第二个方法。

Feign源码解析-LMLPHP

扫描完之后,把所有包含@FeignClient注解的接口都注册到spring的beanfactory去,让开发人员可以@Autowired来调用。这一部分代码我就不贴了,我们只是追求feign的原理流程,太涉及spring源码部分,我不做解释。

========================= 以上是feign注册流程,下面介绍拼装request请求部分 =======================

首先,这里看ReflectiveFeign类,这个类用的是jdk的动态代理

Feign源码解析-LMLPHP

用到代理模式肯定是在发送feign请求之前做一些操作,继续看看请求之前做了哪些操作。

Feign源码解析-LMLPHP

代理拦截每一个FeignClient请求,进入SynchronousMethodHandler的invoke方法,该方法调用executeAndDecode方法,这个方法看名字就知道是创建请求的方法,进去看看。

Feign源码解析-LMLPHP

在该方法发送请求并且解码,解码分为decoder和errordecoder,这两个都是可以重写。这里你可能会问解码器,那编码器呢,feign默认用springEncoder,同样是可以替换成Gson等。

Feign源码解析-LMLPHP

======================= 以上是feign的调用流程,以下是feign使用过程的坑 =================

①feign默认使用线程池,大小是10,这会使得模块间调用丢失header,可以用InheritableThreadLocal解决

②在C版本后默认关闭hystrix,要使用要手动开启

③不要妄想改变feign的逻辑,因为代理模式被写成final,无法修改

④无法在解码器里抛自定义异常,因为feign最终会统一拦截,抛出一个feignexception。你想把统一拦截也改了,那么你可以看看第③坑。

⑤feign的重试机制,默认是1,也就是说超时时间会变成2倍。这个可以通过配置修改。

⑥feign集成的负载均衡器ribbon,feign有个缓存,ribbon也有个缓存,会造成上线延迟,可以修改配置实现。

⑦feign对格式化时间处理有问题

⑧如果你是使用生产者提供api,并且实现该接口,@requestparam可以不用在实现类写,但是@requestbody不写无法映射

以上的坑都是我在实际工作中一个一个爬过来的,希望对大家有帮助!

10-04 17:21