此处的百万并发指的是可以建立至少100w个客户端连接,不考虑业务处理。
反应器模式下的epoll相比起普通的epoll不同在于:普通的epoll在获取到就绪状态的event结构体之后,先判断是什么类型的fd,再进行操作。而reactor先判断是什么类型的事件,再进行操作。本文从头用reactor设计模式来构建一个epoll服务器,这个过程中每次发生IO事件都要注意维护用户空间的数据结构和内核的epoll实例,下面是构建百万并发服务器的详细地步骤(暂不包含并发量测试):
导入相关的包并设置宏
声明事件处理函数
构建存储数据结构
设计一个结构体,用于存储IO相关的信息,并建立全局数组。后续需要不断地维护该数组,一旦发生了IO事件就需要进行更新。结构体的内容包括:1、文件描述符。2、接收到的数据和数据长度。3、要发送的数据和数据长度。4、用于处理接收数据的回调函数,请求连接和连接成功后接收到数据,要调用不同的处理函数。5、用于处理发送数据的回调函数。
编写epoll实例的维护函数
包括修改节点和增加节点的步骤
实现accept事件的回调函数
某个文件描述符接收到数据之后,相应地要维护全局数组,以及epoll实例。全局数组将相应的节点的fd属性进行修改,并初始化数据区为0,同时还要选择处理接收数据的回调函数。
实现recv事件的回调函数
除了相应的数据区,还要注意修改epoll红黑树里相应节点的状态。
实现send事件的回调函数
较为简单,全局数组不需要维护,但是内核的epoll实例需要维护。
、
编写初始化服务器的函数
建立红黑树实例并建立服务器套接字
一共要建立20个服务器套接字。同样的,每成功建立一次,都要维护全局数组和epoll实例。注意套接字描述符的接收数据回调函数选择是accept_cb;
检测就绪状态的fd并处理
根据检测到的事件进行处理,而不是根据文件描述符是服务器套接字还是通信套接字进行处理。值得注意是处理EPOLLIN事件中,虽然代码上调用的都是recv_callback函数,但实际上如果i是服务器套接字,那么调用的依然是accpet_callback。这是因为union特性,union的属性如果都是同一类型,那么进行赋值之后,无论调用哪一个属性都是都可以调用同一个值。
百万并发
- 整个过程涉及到一些时间处理的细节,是为了计算服务器处理并发的效率。
- 全局数组设置很大,这是为了处理百万并发,不是很科学但是能用。
- 百万并发处理一方面体现在三方面,全局数组的大小,epoll模型,服务器套接字的数量。