目的:调用远程业务逻辑方法,并对返回的结果进行处理。可扩展支持多种协议:HTTP, JMS, RMI, FTP等,实现负载均衡,异步调用。默认给出HTTP实现。
概念:
Agent: 我们将这套实现称为agent
Server:远程应用服务, RPC服务的提供者。
Client:客户端,RPC服务的调用者
Agent server:agent在server端的部分
Agent client: agent在client端的部分
Agent group:具有相同业务逻辑的远程服务器的组合,提供相同的远程业务服务。
基本结构:以HTTP方式为例了解一下agent的基本结构
Agent client
组件
|
描述
|
Business client
|
Client端业务逻辑,初始化agent请求,远程调用的发起者
|
Agent client
|
Agent client端流程
|
Request encoder
|
Request编码器,将agent request序列化成文本字符串
|
HTTP executor
|
发送远程调用请求,接收响应结果
|
Load balancer
|
采用轮循方式的负载权衡机制
|
Response decoder
|
响应结果的解码器,发序列化
|
Result handler
|
Agent response结果的处理者
|
Agent server
组件
|
描述
|
Agent servlet
|
J2EE servlet, http agent server side entry
|
Agent service
|
Agent server 端流程
|
Request decoder
|
Request解码器,反序列化agent request
|
Request handler
|
处理agent request
|
App command assembler
|
将agent请求装配成义务逻辑执行参数并初始化agent上下文
|
Agent context
|
Agent上下文,包括会话标识符,上次调用时间等,可供扩展使用,比如为了不改变agent server端业务逻辑的接口,提供给agent系统的实现,可以将一些值放在agent context中。
|
App Logic Command
|
业务逻辑的调用者
|
Response assembler
|
将返回结果和agent上下文装配成agent response
|
Response encoder
|
将agent response序列化成文本字符串
|
如果采用是其他通信方式agent servlet可能就被换成比如jms listener,FTP receiver, RMI service等, 有待以后有需要的时候再实现。
原理:
l 初始化agent group,启动agent client,agent server
l 业务客户端构建agent请求并调用agent client
l Agent client序列化业务请求
l Executor从load balancer中得到当前供调用的agent,通过HttpRequest的body发送业务请求
l Load balancer轮询下一个agent
l Agent server收到请求,调用agent service
l Agent service将请求反序列化,并装配成业务逻辑命令参数的形式,可供业务逻辑调用命令执行,同时初始化agent上下文
l 业务逻辑调用者调用服务器端本地业务逻辑执行并返回结果
l Response装配器将agent context上下文和返回结果装配成agent response
l Response编码器序列化response,并由servlet通过HttpResponse的body发送应答
l Executor收到应答后,从HttpResponse的body里取出agent response的内容
l Response解码器将其解码反序列化成agnet response
l Agent client调用result handler进行返回结果的处理
Client端同步调用顺序图
Client端异步调用顺序图
Server端顺序图
重要模块
传参,序列化,反序列化机制
参数格式
AgentRequest:
AgentResponse
方法参数在添加时,顺序要和远程方法一致,并且方法参数和执行结果在client和server端的classpath上都存在,并且需要保持一致。这样序列化和反序列化才能正常进行,如果采用定制系统,可由业务开发人员自己实现。
序列化,反序列化机制:
可以定制,默认采用XStream
负载均衡
JMS方式可以让同一个agent group的所有agent server都监听在同一个queue上,这是一个简单的负载均衡结构。 是由JMS提供商实现的。
其他的方式采用简单的client side实现,结构如图
对client端每个agentGroup维护一个循环链表存放所有active的agent,用另外一个链表维护所有inactive的agents ,如果在调用的过程中发现某个agent不可达,发生connection error,比如出现SocketException,就判定这个agent不可达,并从active agent链表中移到inactive agent的链表中。在后台还会schedule一个线程周期性地检测inactive链表中的agent是否已经可达,agent server可以提供一个isHealthy方法。如果可达的话,就从inactive链表中移到active链表中。
同步, 异步远程调用
如果业务逻辑对远程调用的执行结果依赖性很强,或者业务逻辑上的调用需要同步,可以使用同步远程调用。异步远程调用可以提高系统的吞吐率。
HTTP
同步:HTTP是一种同步通信协议,client端可以用HTTPComponent,现在HTTPClient也属于它的一个子项目。
异步:由于非阻塞IO的出现,出现了很多framework对socket异步通信的支持。Apache HTTP Component就是其中一个,今年发布了GA release版本。用它可以方便地实现HTTP的异步通信。大体原理如下图所示:
JMS:
同步:可以用jms的TemporaryQueue作为同步调用的信道。JmsExecutor创建一个TemporaryQueue:tempQueue,然后再发送agentRequest到业务逻辑指定的Queue:busiessQueue中,接着JmsExecutor监听在这个TemporaryQueue上,agent server监听在这个busiessQueue上,收到消息后执行agent server端业务逻辑,并将agentResponse发送到tempQueue中,JmsExecutor得到执行结果,然后删除tempQueue。
异步:JMS本身就是一种异步通信方式
RMI:
同步:RMI是一种同步调用方式
异步:需要自己实现Reactor/Connector模式 实现方式类似HTTP的异步结构图。
业务逻辑调用者
业务逻辑调用可以用java反射实现。考虑到反射的代价,使用WeekHashMap对Method元数据描述符进行缓存。
Agent上下文
用ThreadLocal实现
异常处理
如果在远程业务逻辑调用的过程中异常,并抛出到Agent server中,接着传回到客户端,由客户端处理。
源代码:
过两天整理好了补上