实例:一个服务器程序的架构介绍
工作线程的流程:
其中 epoll_or_select_func() 即是上文所说的通过 select()/poll()/epoll() 等 IO multiplex 技术,确定好了哪些 TcpConnection 上有数据到来。我的服务器代码中一般只会监测 socket 可读事件,而不会监测 socket 可写事件。至于如何发数据,文章后面会介绍。所以对于可读事件,以 epoll 为例,这里需要设置的标识位是:
muduo 里面将 epoll_wait 的超时事件设置为 1 毫秒,我的另一个项目将 epoll_wait 超时时间设置为 10 毫秒。这两个数值供大家参考。 这个项目中,工作线程和主线程都是上文代码中的逻辑,主线程监听侦听socket 上的可读事件,也就是监测是否有新连接来了。主线程和每个工作线程上都存在一个 epollfd。如果新连接来了,则在主线程的 handle_io_events() 中接受新连接。产生的新连接的socket句柄挂接到哪个线程的 epollfd 上呢?这里采取的做法是 round-robin 算法,即存在一个对象CWorkerThreadManager 记录了各个工作线程上工作状态。伪码大致如下:
即先从第一个工作线程的 epollfd 开始挂接新来 socket,接着累加索引,这样下次就是第二个工作线程了。如果所以超出工作线程数目,则从第一个工作重新开始。这里解决了新连接 socket “负载均衡”的问题。在实际代码中还有个需要注意的细节就是:epoll_wait 的函数中的 struct epoll_event 数量开始到底要设置多少个才合理?存在的顾虑是,多了浪费,少了不够用,我在曾经一个项目中直接用的是 4096:
我在陈硕的 muduo 网络库中发现作者才用了一个比较好的思路,即动态扩张数量:开始是 n个,当发现有事件的 fd 数量已经到达 n 个后,将 struct epoll_event 数量调整成 2n 个,下次如果还不够,则变成 4n 个,以此类推,作者巧妙地利用 stl::vector 在内存中的连续性来实现了这种思路:
(编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |