原文转载于:https://github.com/
TThreadedServer vs. TNonblockingServer
Introduction
Which Thrift RPC server should MapKeeper use, TThreadedServer or TNonblockingServer? This benchmark compares 2 Thrift C++ RPC servers using StubServer. The focus of this benchmark is to test these 2 servers on a multi-core servers with a limited number (<1000) of concurrent client connections.
TThreadedServer
TThreadedServer spawns a new thread for each client connection, and each thread remains alive until the client connection is closed. This means that if there are 1000 concurrent client connections, TThreadedServer needs to run 1000 threads simultaneously.
TNonblockingServer
TNonblockingServer has one thread dedicated for network I/O. The same thread can also process requests, or you can create a separate pool of worker threads for request processing. The server can handle many concurrent connections with a small number of threads since it doesn’t need to spawn a new thread for each connection.
TThreadPoolServer (not benchmarked here)
TThreadPoolServer is similar to TThreadedServer; each client connection gets its own dedicated server thread. It’s different from TThreadedServer in 2 ways:
- Server thread goes back to the thread pool after client closes the connection for reuse.
- There is a limit on the number of threads. The thread pool won’t grow beyond the limit.
Client hangs if there is no more thread available in the thread pool. It’s much more difficult to use compared to the other 2 servers.
Configurations
Hardware
- 2 x Xeon E5620 2.40GHz (HT enabled, 8 cores, 16 threads)
Operating System
- RHEL Server 5.4, Linux 2.6.18-164.2.1.el5 x86_64, 64-bit
Software
- Thrift 0.6.1
- TNonblockingServer thread pool size: 32 threads
- Client and server run on the same box.
YCSB Workload
- Number of client threads: 300
- Number of requests: 10 million
- Request size: ~60 bytes
- Response size: ~30 bytes
Results
In this benchmark, TThreadedServer performs much better than TNonblockingServer. CPU is maxed out with TThreadedServer, while TNonblockingServer only uses about 20% of CPU time. I’m guessing it’s because the I/O thread is being the bottleneck and worker threads are not getting enough things to do .
Conclusion
TThreadedServer seems like a better fit for MapKeeper since I’m not planning to support thousands of concurrent connections (yet). TNonblockingServer might be a better choice when you face the C10K problem, but you need to make sure the I/O thread doesn’t become the bottleneck. It would be an interesting project to add a new type of Thrift server with a single accept() thread and multiple worker threads handling network I/O and request processing. There is already an open JIRA for this feature in Java. Is anybody interested in working on a similar feature in C++?
相关推荐
server = TServer.TThreadedServer(processor, TServer.TThreadedServer.Args(socket.TCPServer(('localhost', 9090)))) server.serve() ``` 服务器监听9090端口,等待客户端连接。当接收到`sayHello`请求时,它会...
2. **TThreadedServer**:多线程服务器,每个请求分配一个独立的线程处理。 3. **TThreadPoolServer**:线程池服务器,通过线程池管理请求,提高资源利用率。 4. **TForkingServer**:多进程服务器,每个请求创建一...
server = TServer.TThreadedServer(processor, TServerSocket(9090)) print("Starting server...") server.serve() ``` 客户端的使用方式类似,只是需要创建客户端连接并调用服务。Java客户端代码如下: ```...
另外,请注意本文针对的是TNonblockingServer,不包含TThreadPoolServer、TThreadedServer和TSimpleServer。 thrift对网络连接没有使用内存池,最直接简单的性能优化是绑定Google gperftools中的TCMalloc。
transport = TServer.TThreadedServer(processor, TServer.TServer("localhost", 9090, TTransport.TBufferedTransportFactory(), TBinaryProtocol.TBinaryProtocolFactory())) transport.serve() ``` 然后编写...
`TThreadedServer` 是 ThriftPy2 提供的多线程服务器,它会并发处理多个客户端请求。 总的来说,ThriftPy2 是 Python 开发者构建高性能、可扩展的分布式系统的一个有力工具。它简化了跨语言服务通信的过程,同时也...
2. 使用Thrift提供的Server类(如TSimpleServer或TThreadedServer)启动服务器。 客户端的实现则涉及以下步骤: 1. 创建客户端实例,连接到服务器。 2. 调用服务接口的方法进行通信。 `Common`目录可能包含了...
TServer server(TThreadedServer::newThreadedServer(processor, ...)); server.serve(); } ``` 客户端则使用Thrift生成的QT客户端类来连接服务端,创建一个`MyService`的客户端对象,然后调用其`hello`方法: ...
接着,我们可以启动一个`TServer`(如`TThreadedServer`)来监听和处理客户端请求。 在客户端,我们同样需要创建一个`TTransport`和`TProtocol`,然后通过`HelloWorldClient`与服务器建立连接并调用服务方法。例如...
server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) server.serve() ``` 在这里,`TMultiplexedProcessor` 负责管理多个服务处理器,并根据接收到的请求选择正确的处理器进行处理。 ...