Contenu connexe
Similaire à Thrift多路复用的设计与实现
Similaire à Thrift多路复用的设计与实现 (12)
Thrift多路复用的设计与实现
- 1. Thrift 服务(Server)复用的设计与实现
作者:billowqiu@163.com
介绍
Thrift 作为一个跨语言的 rpc 框架,为后端服务间的多语言混合开发提供了高可靠,可
扩展,以及高效的实现。但是自从 2007 年 Facebook 开源后的 6 年时间内一直缺少一个多路
复用的功能(Multiplexing Services),也就是在一个 Server 上面实现多个 Service 调用。比如
要实现一个后端服务,很多时候不仅仅只是实现业务服务接口,往往还会预留一些调试,
监
控服务接口,以往要实现多个 Service 在一个 Server 上面调用,要么将多个服务糅合成一个
庞大的服务(图 1)
,要么将多个 Service 分摊到不同的 Server 上(图 2)
。最近的版本 0.9.1
终于实现内置的多路复用,
本文简要分析一下该功能的设计与实现,
并提供一个简单的示例。
图1
- 4. 图4
图5
Client 增加一个 MultiplexProtcol 实现,在原有协议基础上增加 ServiceName 的打包
Server 增加一个 MultiplexProssor 实现,分离不同的具体服务
实现
从 Release-Notes 看到目前已经有 Java,Delphi,C#,C++几个语言实现了该功能,具体到
C++实现按照 THRIFT-1902 的介绍,是直接移植的 java 版本。
新增代码
protocol/TMultiplexedProtocol.h
protocol/TMultiplexedProtocol.cpp
- 5. protocol/TProtocolDecorator.h
processor/TMultiplexedProcessor.h
主要逻辑
1)
TMultiplexedProtocol 类重写 writeMessageBegin_virt 方法, Service 的函数名前新增了
在
ServiceName,并附带了一个分隔符;该类采取了 Decorator 模式将绝大部分操作转发到
实际的 protocol 对象。
2)
TMultiplexedProcessor 类增加了一个存放 service 的 map,
typedef std::map< std::string, shared_ptr<TProcessor> > services_t;
key 为 ServiceName , 这 样 在 process 方 法 中 先 解 出 TMultiplexedProtocol 传 递 过 来 的
ServiceName,
通过该 key 查找到对应的 Processor 对象,
再调用该 Processor 的 process 方法,
这样就完美的实现了多个 serivice 的共存。
使用示例
IDL:
namespace cpp thrift.multiplex.demo
service FirstService
{
void blahBlah()
}
service SecondService
{
void blahBlah()
}
Server:
int port = 9090;
shared_ptr<TProcessor> processor1(new FirstServiceProcessor
(shared_ptr<FirstServiceHandler>(new FirstServiceHandler())));
shared_ptr<TProcessor> processor2(new SecondServiceProcessor
(shared_ptr<SecondServiceHandler>(new SecondServiceHandler())));
//使用 MultiplexedProcessor
- 6. shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
//注册各自的 Service
processor->registerProcessor("FirstService", processor1);
processor->registerProcessor("SecondService", processor2);
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
Client:
shared_ptr<TSocket> transport(new TSocket("localhost", 9090));
transport->open();
shared_ptr<TBinaryProtocol> protocol(new TBinaryProtocol(transport));
shared_ptr<TMultiplexedProtocol> mp1(new TMultiplexedProtocol(protocol, "FirstService"));
shared_ptr<FirstServiceClient> service1(new FirstServiceClient(mp1));
shared_ptr<TMultiplexedProtocol> mp2(new TMultiplexedProtocol(protocol, "SecondService"));
shared_ptr<SecondServiceClient> service2(new SecondServiceClient(mp2));
service1->blahBlah();
service2->blahBlah();
总结
Thrift 通过在客户端采取的 decorator 模式巧妙的在协议层将 ServiceName 传递到服务端,服
务端通过常见的手段将 ServiceName 和具体的 Processor 进行映射,完美的解决了 Server 对
Service 的多路复用问题。
参考资料
1.
2.
3.
4.
http://thrift.apache.org/docs/concepts/
https://issues.apache.org/jira/browse/THRIFT-1902
https://issues.apache.org/jira/browse/THRIFT-563
http://bigdata.impetus.com/whitepaper