1.10 构架简介
设计目标
- 跨语言跨平台
- 编码层可替换
- 传输层可替换
- 具有扩展机制
构架图
+------+ +--------+
|Invoke| |Execute |
+------+ +--------+
| ^ | ^
v | v |
+--------------+ +--------------+
|InvokeHandlers| |InvokeHandlers|
+--------------+ +--------------+
| ^ | ^
v | v |
+------+ +------+ +------+ +------+
|Encode| |Decode| |Encode| |Decode|
+------+ +------+ +------+ +------+
| ^ | ^
v | v |
+----------+ +----------+
|IOHandlers| |IOHandlers|
+----------+ +----------+
| ^ | ^
v | v |
+----------+ +--------+
|Transports|---------------------->|Handlers|
+----------+ +--------+
^ |
| |
+---------------------------------+
____ _ _ ____ _ _ ___ ____ ____ ____ _ _ _ ____ ____
| | | |___ |\ | | [__ |___ |__/ | | | | |___
|___ |___ | |___ | \| | ___] |___ | \ \/ | |___ |___
构架简介
通过上面的构架图,我们可以大致了解 Hprose RPC 的工作流程。上图左面部分是客户端,右面部分是服务端。客户端和服务端的执行流程是对称且相反的两个过程。
客户端首先发起调用,原始的调用请求会通过调用处理器进行处理,之后经过处理的调用请求被编码为序列化后的 RPC 请求,编码之后的请求再通过输入输出处理器进行处理,最后通过传输层发送到服务端。
服务端的处理器将接收到的客户端发来的序列化后的 RPC 请求转发给输入输出处理器进行处理,然后处理过后的序列化 RPC 请求被解码为原始调用请求再转发给调用处理器,调用处理器处理后,请求被执行,并将执行结果按原路层层返回给客户端。
在该调用过程中,客户端和服务端的各自存在一个上下文对象(Context
)。也就是说,除了请求和结果会在以上过程中被传递以外,上下文对象也会在以上过程中被传递。但是上下文对象并不会从客户端传递给服务端,也不会从服务端传递给客户端,上下文对象在客户端和服务端是各自独立的。
客户端上下文对象(ClientContext
)和服务端的上下文对象(ServiceContext
)继承自同一个上下文对象(Context
)的结构。通过这种抽象,就可以将调用处理器(InvokeHandler
)和输入输出处理器(IOHandler
)设计为在客户端和服务端通用的形式了。
调用处理器(InvokeHandler
)和输入输出处理器(IOHandler
)用来实现可扩展的插件机制。
它们具有相同的工作模式,只是接口和所处理的数据有所不同。
客户端和服务的各自拥有独立的编解码器(Codec
),默认的编解码器使用 Hprose 序列化和 Hprose RPC 协议进行编解码处理。
编解码器是可替换的,通过替换编解码器,Hprose 客户端或服务端可以变身为其它 RPC 的客户端或服务端。例如,如果实现了 JSONRPC 编解码器,Hprose 客户端和服务端就完全可以作为 JSONRPC 的客户端和服务端来使用,并且可以与其它方式实现的 JSONRPC 客户端或服务端进行互通。
在上面的构架图中,客户端的传输层被抽象为一个 Transport
对象,而服务的传输层处理器被抽象为一个 Handler
对象。可以为不同的传输协议提供不同的实现,将实现的传输层对象在客户端和服务端的进行注册后,就可以使用该传输层协议进行通讯了。客户端和服务端都可以注册多种传输协议,并可以增加替换,还能混合使用。