概述
现在很多项目都基于微服务开发,而对于开发来说,最困扰的就是本地服务间的调试。在此之前在网上给出的方案都是 直接在feign 调用接口 写死url,但这会出现团队成员不小心将调试的url提交到仓库中,无形的增加了产线事故的产生。本文将介绍一下我自身基于项目改造的 可配置feign 路由的方案。
Openfeign的初始化
-
在项目启动阶段,OpenFeign 框架会发起一个主动的扫包流程,从指定的目录下扫描并加载所有被 @FeignClient 注解修饰的接口。
-
OpenFeign 会针对每一个 FeignClient 接口生成一个动态代理对象FeignProxyService,这个代理对象在继承关系上属于 FeignClient 注解所修饰的接口的实例。
-
这个动态代理对象会被添加到 Spring 上下文中,并注入到对应的LocalService 服务。
-
LocalService会发起底层方法调用。实际上这个方法调用会被 OpenFeign 生成的代理对象接管,由代理对象发起一个远程服务调用,并将调用的结果返回给LocalService。
整个过程如下图:
而我们添加动态如果就是在OpenFeign通过动态代理技术创建代理对象的过程中,将对应的路由设置到对应的代理对象中。
代码实现
在此我将简单的阐述一下整体的实现思路,在openFeign 加载代理对象时,去设置它的target 对象中的url,将原本需要从注册中心拉取订阅服务列表从而获取对应的服务路由地址,替换成读取配置文件中的url,从而实现调用本地服务。
1、自定义参数
feigns:
user: http://localhost:8102
system: http://localhost:8106
2、feign 注解设置 value 用于识别服务
@FeignClient(value = "user")
public interface IUserClient {
XXXX
}
3、启动时将对应的url设置进对象中
@Slf4j
@Configuration
@EnableConfigurationProperties(XXXProperty.class)
public class FeignConfiguration {
@Resource
private XXXPropertyproperty;
private static final String EVN_DEV="dev";
private static final String EVN_LOCAL="local";
@Bean
public Targeter getTarget() {
return new Targeter() {
@Override
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, Target.HardCodedTarget<T> target) {
String systemRouter = null;
//只有在dev 环境才启动
if (EVN_DEV.equals(System.getProperty("spring.profiles.active"))
|| EVN_LOCAL.equals(System.getProperty("spring.profiles.active")
)&&ObjectUtil.isNotEmpty(property)){
systemRouter = property.getFeigns().get(target.name());
}
if (systemRouter != null) {
log.info("use systemRouter for:" + target.name());
return feign.target(new Target.HardCodedTarget<T>(target.type(), target.name(), systemRouter));
}
return feign.target(target);
}
};
}
}
至此整个功能就实现完毕,本文只是介绍怎么实现,至于openFeign 的加载及其原理,在此不做细讲。