Epoll 轮询机制 和libevent的多线程实现
最近需要使用Linux开发,需要在网络连接上复用。原有程序是使用每个请求进行一次创建线程,执行事务,销毁线程,这种模式来实现多个请求。现在希望能够基于线程池实现请求复用。实际上效果应该不会太好,因为:
- 请求都是内部高速Lan连接
- 单台服务器请求数不会超过500
- 属于CPU计算密集型;I/O较少。因此,主要耗时,还是服务本身,平均100ms/每核;假设线程创建销毁1ms,那么这1%即使完全节省下来,也不会有提高。
- epoll模型和select模型。理论上,此时epoll不会比select高效,理由Lan高速连接,连接都是Active而不是wait。当然,无论选择哪种,都不会提升服务质量,理由3
不管怎样,继续学习epoll的使用。
epoll用于Linux2.6上,主要用于处理高并发连接。
epoll 有3个函数:epoll_create,epoll_ctl,epoll_wait
外加一个用于关闭句柄的 close函数;1个对象struct epoll_event。
创建句柄(Handle)
int handle = epoll_create(int size);
返回的是一个句柄,这个句柄最后是需要close的(所有句柄,都需要close,无论windows还是linux,句柄实际上是一个内核对象)。
size表明可监听的并发连接数目,在Linux2.6.8以后,该参数被忽略,仅仅向下兼容考虑。
注册事件
int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);
epfd,创建时候的句柄
op,operation的意思,表示执行何种命令,
EPOLL_CTL_ADD;增加
EPOLL_CTL_MOD:修改
EPOLL_CTL_DEL:删除
常见的增删改(不包含查询,实际内部需要使用查询)
//常见的如果存在就修改,否则增加,Redis中有如下源码
int op = eventLoop->events[fd].mask == AE_NONE ?
EPOLL_CTL_ADD : EPOLL_CTL_MOD;
struct epoll_event{
__uint32 events;//epoll事件类型
epoll_data_t data;//用户数据
};
EPOLLIN:触发该事件,有可读数据。(包括对端SOCKET正常关闭);
EPOLLOUT:触发该事件,有可以写数据;
EPOLLPRI:紧急数据处理(可读),urgent data available for read
EPOLLERR:发生错误;
EPOLLHUP:暂时被挂断;
EPOLLET: ET模式
EPOLLONESHOT: 只监听一次事件,用完即结束。
等待事件
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
Epoll是支持多线程的,即多个线程都可以监听各自的epoll,而这些Epoll都监听同一端口,而不用担心惊群。
- libevent中的多线程实现
由于libevent的event base
实现方式:2种
- 类似于memcache的实现,即一个masert,通过管道pipie与子线程通信。其实这个类似于nginx的方式
- 因为,epoll是可以多线程安全的。因此,每个线程创建一个event base,然后关联同一个端口的fd。
下一篇: express创建ejs项目