详情-思想者
基于消息的分布式RPC框架
发布于 2018-12-24 ,0条评论,178次浏览

一、一个简单模型

任何基于消息的PRC框架都离不开三个参与者,即生产者、消费者、MOM。本文正是基于这种简单模型进行技术封装,以tibco作为消息中间件,使得开发人员进行简单配置就能够使用RPC框架。对于框架的设计者而言,需要考虑如下问题:
1、声明,要告知spring容器这是一个远程服务,启动阶段和运行阶段需要特殊处理。
2、接口层自定义,要明确接口与Q的绑定关系,明确序列化方式。
3、方法层自定义,是同步还是异步,优先级怎么样,超时时间是多少,是否支持事务。
4、队列层自定义,需要针对Q自定义连接工厂,消费者并发数,消息选择器。
基于以上考虑点,本例通过使用xml+注解来完成相关申明和自定义,下面通过举例说明:
1、@Mdpwired
这个注解是为了申明这是一个mdp服务,客户端spring容器启动时,扫描到此注解,就会生成一个远程代理,并注入。形如:
2、@MdpService
这个注解用于接口层自定义。这里面可以定义服务端监听的Q名称。服务端spring容器启动时会扫描此注解,根据Q相关信息注册监听,并建立Q与接口的绑定关系。形如:
3、@MdpMethod
这个注解用于方法层自定义。在runtime阶段,系统会解析注解里的属性值并赋予到当前的方法特性中,例如同步异步、超时时间、优先级等。形如:
4、xml>MdpBeanPostProcessor
MdpBeanPostProcessor非常重要,这是mdp初始化的核心类,客户端和服务端都需要在xml中声明并配置。MdpBeanPostProcessor可以指定连接工厂,也可以针对某个Q进行配置并自定义特性。形如:
通过以上配置,系统可以实现:
1、服务端的一个接口可以监听多个Q。对应@MdpService注解。
2、客户端调用接口的某个方法时可以指定Q。对应@MdpMethod注解。
3、一个Q也可以接受不同的service请求。此处,读者可能存在异议。如果serviceAImpl和serviceBImpl部署在同一个应用容器中,这一点是可以实现的。

二、mdp运行机制-启动阶段

上文曾提到过MdpBeanPostProcessor的xml配置,这个bean承担了客户端和服务端MDP初始化的全部工作。MdpBeanPostProcessor如果扫描到@MdpMethod注解则会给客户端生成代理对象,如果扫描到@MdpService注解,则会在服务端注册监听。
1、客户端初始化过程:
2、服务端初始化过程:

三、mdp运行机制-调用阶段

客户端调用远程方法时,会被方法拦截器拦截,执行代理对象的内部逻辑。代理对象会将调用方的接口名、方法名、Q名、是否同步等信息封装到请求对象中,然后发送消息到tibco。如果是同步请求,在发送消息时,客户端将会创建一个随机的临时Q,形如$TMP$.EMS-SERVER.41BF5BD90D4F3349.2,并监听此Q。客户端会在超时时间范围内同步等待这个临时Q的返回数据,借此模拟同步请求的效果。客户端具体调用过程如下:
服务端监听到消息后,将消息内封装的接口和方法信息解析出来,然后执行反射。服务端具体调用过程如下:

四、设计思路

    如果上文提到的初始化和调用过程让人眼花缭乱,那我们需要跳出细节的怪圈,从更高角度去思考MDP的设计和实现,去分析对象和行为的关系。因为再复杂的代码也是从基本的需求出发,需要通过模型去演变。下图是基于本人的理解所画,可能与原设计者的意图有所出入,仅供参考。  

从上图中我们可以清晰的看到各个核心类在整个交互体系中的位置。MdpBeanPostProcessor是初始化的核心类,客户端和服务端启动时都会去加载。MdpInvokerProxyFactoryBean充当代理和拦截器的角色,每次调用远程方法都要经过它。MdpRequestor则会包装生产者和消息对象,用来发送消息。MdpServiceBusExporter用来监听服务端的消息,并根据消息里面的接口信息锁定对应的服务端接口。MdpInvokerServiceExporter根据接口和方法信息,使用反射机制执行服务端的业务逻辑。我们也可以从以下三个角度去思考这个设计:
1、Q级别行为
tibco只认识Q和消息,它并不care接口方法之类的概念,所以客户端和服务端需要有对象来对接Q级别的发送和监听,因此有了MdpRequestor和MdpServiceBusExporter。
2、接口级别行为
接口和方法的概念是业务端附加的,我们既要满足一个接口监听多个Q,也要满足根据不同的方法发给不同的Q。既要根据不同的接口生成不同的代理,也要根据不同的接口调用各自的反射。业务端采用合理的绑定就能够达到这一效果,因此产生了MdpInvokerProxyFactoryBean和MdpInvokerServiceExporter。
3、初始化行为
客户端和服务端把需要用到的配置,代理,监听等全部初始化好,调用时直接拿来用。因此有了MdpBeanPostProcessor。

五、技术体系

本例使用技术大多是spring体系下的,技术方向是bean加载、注解、代理、拦截、反射以及jms规范等。具体如下: