半年前偶然看到一叫spserver的服务器框架,它将windows下IOCP移植到到libevent,并且以HSHA,LF两种模式实现了服务器框架.我做了点功课,写点心得.
一般来说在设计一个服务器网络框架的时候,需要用到线程池,里面的线程负责执行服务端所有代码.这些代码总的来说可以分为两类:
通常情况下他们是分离的,网络IO部分不需要管理业务逻辑具体做什么工作,而后者也不关心数据怎么得来,怎么送到网络上.两者就是一个生产者消费者关系.
这里讨论的HSHA就是网络IO部分为异步模式,而业务逻辑部分为同步模式.即:
同步和异步两部分采用一个作业队列(jobQueue)来实现结合,一些细节:
以下代码说明大概的处理流程:
1: class job_queue;
2: class msg_free_queue;
3: class thread_pool;
4: int main()
5: {
6: job_queue jobs;
7: msg_free_queue msg_to_free;
8: thread_pool job_thread;
9: thread_pool clean_thread;
10: server_init_and_listen();
11: run_accept_thread();
12: while(!exit_falg){
13: run_iocp_event_loop(&jobs,&msg_to_free);
14: while(job_queue.size() > 0){
15: job_thread.push(job_queue.pop_front());
16: }
17: while(msg_to_free.size() > 0){
18: clean_thread.push(msg_to_free.pop_front());
19: }
20: };
21: }
下面是一些题外话:
你也看到了,只有一个线程负责处理IO部分,那么性能如何呢?
这个吧,其实大多数时候,你的服务器性能瓶颈不再网络IO部分,而在业务逻辑处理部分,在那里可能产生磁盘IO,数据库操作等.我个人觉得但线程IO已经足够了.采用IOCP这样高效的IO模型是为业务逻辑处理腾出资源,因为一个高效的服务端不是看你每秒能收发多少数据,而是看业务处理能力.另外单线程的IOCP也有很多好处,首先就是锁的问题解决了,其次就是资源的管理简单了,这两个问题都是比较棘手的东西.
我编译了spserver的代码,用asio的乒乓测试客户端程序做了一下压力测试,结果你可能也猜到了,IO吞吐量并不算很高,而且多核CPU上,只有一个CPU达到了100%利用率,而另外几个CPU则利用率不足50%.如果你跟我一样,是一个完美主义者,我们可以这样改进它:
将上面的代码中,监听工作和Accept线程分离出来,主循环那的部分(while那一块和相关的上下文环境)封装成一个模块,每一个模块都有自己完成端口句柄,当连接建立时,做一个简单的负载均衡,为新建立的连接的套接字句柄选择一个完成端口句柄并绑定.于是就变成了下面的样子:
1: class job_queue;
2: class msg_free_queue;
3: class thread_pool;
4: int nod();
5: int main()
6: {
7: thread_pool io_thread_nods;
8: io_thread_nods.set_thread_count(4);
9: server_init_and_listen();
10: run_accept_thread();
11: while(true){
12: io_thread_nods.run(nod);
13: }
14: }
15: int nod()
16: {
17: job_queue jobs;
18: msg_free_queue msg_to_free;
19: thread_pool job_thread;
20: thread_pool clean_thread;
21: while(!exit_falg){
22: run_iocp_event_loop(&jobs,&msg_to_free);
23: while(job_queue.size() > 0){
24: job_thread.push(job_queue.pop_front());
25: }
26: while(msg_to_free.size() > 0){
27: clean_thread.push(msg_to_free.pop_front());
28: }
29: };
30: }
OK,完工.
文章信息
作者:J.Cheen
出处:www.cnblogs.com/cheen