关于异步,我找了很多资料,java方面的比较多,可c的少之又少,很多就是简单提一下,也么说怎么用,最后终于还是自己研究出来了
异步分为服务端异步与客户端异步两部分,理论上他们两者是无关的,不论服务端同步与否,客服端都可以做成异步的。
客户端异步
客户端异步比较简单,服务端可以使用任何server,TThreadPoolServer或TNonblockingServer等随意,客户端不调用自动生成的函数原型,
改为分别调用分拆开来的send与recv两个即可,例如下面代码:
//函数名为invoke,函数原型为:
string invoke(1:WS_OP_TYPE type, 2:string msg);
//同步调用方式代码为(retstr为返回字符串,另外两个为传入参数):
client.invoke(retstr, WS_OP_TYPE::WS_OP_STORE_DEVICE_ACTION, msgstr);
//异步调用方式代码为:
client.send_invoke(WS_OP_TYPE::WS_OP_STORE_DEVICE_ACTION, msgstr);
client.send_invoke(WS_OP_TYPE::WS_OP_STORE_DEVICE_ACTION, msgstr1);
client.recv_invoke(retstr);
client.recv_invoke(retstr1);
send_invoke即为调用invoke时的发送消息过程
recv_invoke即为调用invoke时的接收消息过程
这两个接口代码会同invoke接口一起生成,我们直接调用即可
通过这样简单的调用即可实现客户端异步,即发送与接收中间可以处理其他业务流程,
也可以像上面代码中使用同一客户端分别发送几次完成后再分别全部接收,框架会分别接收到每一个调用的结果,
到这里就会有一个疑问:同时调用那么多次,如何才能识别返回的消息是那次调用返回呢?
比较简单的做法就是调用过程中加一个序列号的参数,每次调用返回的序列号都相同,而不同次调用的序列号都不同。
thrift也提供了异步客户端的实现,但生成代码时需要添加cob_style属性,即运行以下命令:
thrift --gen cpp:cob_style a.thrift
生成的代码中包含一个AsynClient的类以供实现异步调用,初步看到是使用回调函数进行的。
此种方法正在研究中,随后会将研究结果补充上来
服务端异步
Thrift服务端异步通过使用TNonblockingServer实现,TNonblockingServer依赖libevent,即编译Thrift时系统必须已经安装libevent,否则编译出的Thrift不包含TNonblockingServer的实现,ubuntu安装libevent使用如下命令:
sudo apt-get install libevent-dev
同时使用TNonblockingServer时,应用程序编译命令也需要添加 -lthriftnb -levent。使用TNonblockingServer的代码如下:
int main(int argc, char **argv)
{
int port = 9090;
shared_ptr handler(new DataServiceSystemHandler());
shared_ptr processor(new DataServiceSystemProcessor(handler));
shared_ptr serverTransport(new TServerSocket(port));
shared_ptr transportFactory(new TBufferedTransportFactory());
shared_ptr protocolFactory(new TBinaryProtocolFactory());
shared_ptr threadManager =
ThreadManager::newSimpleThreadManager(10);
shared_ptr threadFactory =
shared_ptr(new PosixThreadFactory());
threadManager->threadFactory(threadFactory);
threadManager->start();
TNonblockingServer server(processor,
protocolFactory,
port,
threadManager);
printf("Starting the server...\n");
server.serve();
printf("done.\n");
return 0;
}
TNonblockingServer也可以不使用线程池,仅仅使用单线程处理,此时只需在构造TNonblockingServer时不添加threadManager即可,如以下代码:
TNonblockingServer server(processor,
protocolFactory,
port);
TNonblockingServer区别于其他server(例如TThreadPoolServer)在于:TNonblockingServer使用epoll与udp协议(TFramedTransport传输方式)实现,这样既可使用很少的线程实现大并发,而不会像TThreadPoolServer那样并发受线程池线程数限制。
所以使用TNonblockingServer的异步也仅仅是server内部实现思想上的异步,将线程池的阻塞线程处理请求改为了非阻塞串行处理,TNonblockingServer调用serve方法时本身还是会阻塞调用线程。
调用serve方法不阻塞方法应该也很多,并且还有服务端callback方式,有时间找到再补上来吧