我们为什么需要一个通信组件
最近几年面试了无数同学,大部分全是Spring体系的全家桶,确实,这玩意挺好用,常用的小玩意确实用这个全家桶就够了。不过,不晓得大家有没有遇到过这个场景,在通信过程中额外的做一些事情,例如报文的加解密,压缩/解压缩,流控处理,路由处理,信息透传等等,能使用的做法无非是filter或者是interceptor,这没问题,不过,你使用的通信框架是什么呢?RestTemplate?OpenFeign?Dubbo?gRPC或者是其它的玩意?那我如果要做那些目的的话,我是否要为所有的通信框架单独写?我们再来看看通信技术栈,微服务间调用要使用通信,网关与下游服务调用要使用通信,ESB与下游服务调用,要使用通信,甚至是ServiceMesh与下游服务调用,同样要使用通信。就算我们都是独立的技术栈,没问题,那我上面描述的这些处理咋办?自己写?呃,我估计大家已经看不下去了,这都什么玩意啊,我们能否自己做一个标准通信组件,一统通信技术栈的江湖呢?
如何设计一个通信组件
市场上的通信组件太多了,除了Spring全家桶,开源的还有gRPC,腾讯的tRPC,还有新浪微博的motanRPC,其实挺复杂的,而通信这个事情,应该是很单纯的事情,我们关注的点无非以下几个
- 服务模型。名字啊,访问点啊,使用的底层协议(http,tpc,mq,file)啊什么的
- SLA。服务的级别。拜托,要想一下你的服务是给谁用的,咱们写代码,也有private/protected/public的区别啊
- 服务端的处理逻辑
- 客户端的处理逻辑
- 编解码
- 压缩解压缩
- 流控
- 路由
还有什么吗?先就以上的说吧,足够用了。其实大家仔细看一下,这玩意就是个处理流程,或者是一个链式模型,部分处理是非必须的并且一定是有顺序的,因此,设计一个通信组件,最简单的方式就是用一个责任链模式,把这些内容串联起来。
一个最简单的责任链
我们可以简单画一个Spring体系的通信过程。由于现在Spring的代码写的并不好,所以我把过程以链式方式表示
这个过程过于简单,没什么可说的。我们加上企业级的规范处理,就变成了下面这个样子
这个只是http协议的处理过程,那如果是MQ呢,文件呢?只是处理链路的长和短的区别吧?所以,通信过程应该是一个可编排,可扩展的一个责任链处理方式。
说到责任链,在抽象层面上,就变的非常容易了,一个是流程处理引擎,一个是链的定义,简单来说,就是这么个类关系图
- 执行引擎。负责对责任链的编排,标识链的个数,顺序以及链的实例instance,便于引擎执行时对每一个链进行调度
- 上下文。我写的不全,咱们只关心重要的。我们搞的是协议,那以最简单的方式,协议头和协议体
- 链。责任链的抽象接口定义,我们只需定义名称和invoke函数即可,具体实现由链的具体实现去吧
到此,一个简单的责任链就设置完了,其实它啥也没干,只是做了定义。
做我们自己的通信组件
具备了上面的一点知识后,按照流程和责任链的处理方式,通信组件就非常简单了
上图是一张腾讯开源的tRPC,他这么分层不是不行,但是不好,我画一个我自己的吧
这样看起来就清爽多了也简单多了,我再加一个架构图
这个对腾讯那个稍微改造了一下……
架构图做到了这个份上,代码就是分分钟的事情,我大概用了2天就敲出了一个来,并不复杂,重点是,你要用他来干吗。
通信组件能干吗?
开篇的时候,我说需要通信场景的很多,网关、微服务、服务网格、ESB……而且他们都有路由需求、安全需求、流控需求,呃,通信组件最大的价值,就是统一通信技术栈。
我多画一个图,可以很明显的看出网关、通信组件和其它组件的包装关系,而通信组件,天生就是为了分布式通信而活,是面向应用的。到此,建议大家在自己的公司内部统一通信技术栈,让Spring这个体系见鬼去吧。