并发性不是太高服务器程序使用这个模式基本就可以满足。
主线程只负责监听文件描述上是否有事件,如果有就立即将该事件通知到工作线程。读写数据、接受新的连接以及处理客户端的消息都在工作线程。
工作流:
1)主线程往 epoll 内核事件表中注册 socket 上的读就绪事件
2)主线程调用 epoll_wait 等待 socket 上有数据可读
3)当 socket 上有数据可读时, epoll_wait 通知主线程。主线程则将 socket 可读事件放入请求队列。
4)睡眠在请求队列上的某个工作线程被唤醒,他从 socket 读取数据,并处理客户请求,然后往 epoll 内核事件表中注册该socket 上的写就绪时间。
5)主线程调用 epoll_wait 等待 socket 可写。
6)当 scoket 可写, epoll_wait 通知主线程。主线程将 socket 可写事件放入请求队列。
7)睡眠在请求队列上的某个工作线程被唤醒,它往 socket 上写入服务器处理客户端请求的结果。
公司游戏后端架构基本遵循此工作流:
主线程是一个循环,每一帧使用 epoll_wait 等待事件发生,有可读写事件或请求连接事件时处理这些事件,将可读事件的内容 recv出来创建一个消息对象,放入事件处理队列中,只不过请求连接事件是直接在主线程处理的。
CMain 对象初始化时就创建 pack_deal 工作线程池。工作线程则每一帧从工作队列里取出消息对象及 sock 进行处理,处理完之后再写入一个消息对象放在队列中,再由主线程 send 出去。
主要不同是读取和发送还有创建连接是在主线程,然后工作线程池容量可以在 配置文件 .conf 中配置,日常只是配置一个。
大多数游戏服的同时在线人数在 20 左右,最高的新区可达60人,老区每天大概30人,所以使用这种模型足够应付。