撸了一个 Feign 增强包

image

前言

最近准备将公司的一个核心业务系统用 Java 进行重构,大半年没写 JavaJDK 都更新到 14 了,考虑到稳定性等问题最终还是选择的 JDK11

在整体架构选型时,由于是一个全新的系统,所以没有历史包袱,同时团队中也有多位大牛坐镇,因此我们的选项便大胆起来。

最终结果就是直接一把梭,直接上未来的大趋势:Service Mesh,直接把什么 SpringCloudDubbo 这类分布式框架全部干掉。

本次的重点不是讨论 Service Mesh 是什么、能解决什么问题、为什么选择它,毕竟我也在学习阶段,啥时候整明白线上也稳定了再和大家来交流。

问题

既然方向定了就开始实际撸码了,不过刚一开始就验证了”理想很丰满、现实很骨感“;

由于我们去掉了 SpringCloudDubbo 这类框架,服务的注册、发现、负载均衡等需求全部都下沉到 Service Mesh 中提供了。

但对于开发来说依然希望可以调用本地方法的方式来调用远程服务,这在 SpringCloud 这类框架中是很容易实现的,框架本身就有很好的支持。

回到我们这个场景,需求其实很简单,就是想达到 SpringCloud 中的 Feign 这样的声明式+注解的方式调用。

image
    @Autowired
    private StoreClient client ;
    
    Store store = client.update(1, store)

使用 spring-cloud-openfeign 这个包其实就能实现上述的需求了,但这样会引入一些我们根本不会使用的 SpringCloud 的相关依赖,让人感觉”不干净了“;同时也和 Service Mesh 的理念相反,其中的一大目的就是要降低这类框架的侵入性。


其实 spring-cloud-openfeign 的核心就是 Feign,本身它也是可以开箱即用的,所以便尝试看 Feign 自己是否支持这样的用法。

image

通过官方文档可以得知:是可以定义接口的形式来调用远程接口的,但它本质上是不依赖其他库便可以使用,所以它本身是没有和 Spring 整合也是合情合理,但也就造成了没有现成库可供我们使用。

我们自然是不想写上图红框处的代码的,希望所有接口直接注入就可以使用。

使用

因此结合以上的需求便有了这个库 feign-plus

它的使用流程其实就是翻版的 spring-cloud-openfeign

@FeignPlusClient(name = "github", url = "${github.url}")
public interface Github {

    @RequestLine("GET /repos/{owner}/{repo}/contributors")
    List<GitHubRes> contributors(@Param("owner") String owner, @Param("repo") String repo);
}

SpringBoot 入口进行扫描:

@SpringBootApplication
@EnableFeignPlusClients(basePackages = "top.crossoverjie.feign.test")
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

Spring 上下文中直接注入使用:

    @Autowired
    private Github github ;
    
    List<GitHubRes> contributors = github.contributors("crossoverJie", "feign-plus");
    logger.info("contributors={}", new Gson().toJson(contributors));    

所以当我们需要调用一些外部第三方接口时(比如支付宝、外部 OpenAPI)便可类似于这样定义一个接口,把所有 HTTP 请求的细节屏蔽掉。

当然也适合公司内部之间的服务调用,和咱们以前写 SpringCloudDubbo 时类似;服务提供方提供一个 Client 包,消费方直接依赖便可以调用。其他的负载均衡、容错之类的由 Service Mesh 替我们完成。

对于内部接口,也可以加上 @RequestMapping("/path") 注解:

image

在请求时便会在 url 后拼接上 /order,这样在配置 feign.order.service.url 时只需要填入服务提供方的域名或 IP 即可。


feign-plus 也支持切换具体的 httpclient,默认是 okhttp3,通过以下配置便可更改。

# default(okhttp3)
feign.httpclient=http2Client

当然也有其他相关配置:

feign.plus.max-idle-connections = 520
feign.plus.connect-timeout = 11000
feign.plus.read-timeout = 12000

实现

最后简单聊聊是如何完成的吧,其实本质上就是 spring-cloud-openfeign 的浓缩版。

其中最为核心的便是 top.crossoverjie.feign.plus.factory.FeignPlusBeanFactory 类。

image

该类实现了 org.springframework.beans.factory.FactoryBean接口,并重写了 getObject() 方法返回一个对象。

这段代码是不是似曾相识,其实就是 Feign 的官方 demo

这里所返回的对象其实就是我们定义的接口的代理对象,而这个对象本身则是 Feign ,所以再往里说:我们的 http 请求编解码、发起请求等逻辑又被这个 feign 对象所代理了。

image

这个 HardCodedTarget 则是 Feign 内部用于代理最终请求的对象。

有一个小难受的地方:这样的自己定义 Bean 然后注入对象 Idea 是识别不了的,认为当前上下文没有该 Bean,但是 spring-cloud-openfeign 却可以识别。


由于 Feign 支持多个客户端,所以这里的客户端可以通过配置文件动态指定。

image

利用 SpringBoot 提供的 @ConditionalOnExpression 注解可以根据配置动态的选择使用哪个 httpclient,也就是动态选择生成哪个 Bean

总结

这个库的逻辑非常简单,本质上就是封装了 Feign 并提供了 SpringBoot 的支持,欢迎有类似需求的朋友下载使用。

feign-plus源码:https://github.com/crossoverJie/feign-plus

你的点赞与分享是对我最大的支持

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342