锁定老帖子 主题:来说说epoll+线程池
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (11)
|
|
---|---|
作者 | 正文 |
发表时间:2008-05-03
等有机会展示一下我的cobra_linux吧,虽然它现在还不是很完美。 #ifndef _LC_COBRA_EPOLLER_H #define _LC_COBRA_EPOLLER_H /* * Copyright(c)2008 * * 文件名称: Epoller * 文件标识: * 摘 要: Epoller是我自己封装的epoll,仿照 Windows平台的IOCP(完成端口)来实现类似 的一套高性能的网络底层io策略。 Epoller实现的原理是: 但个线程来循环我们的epoll来等待底层的网络事件 当有事件的时候,我们就把这些事件对应的数据放入 到我们的上层Epoller缓冲队列中,并且发出信号,通知 阻塞在这个上面的线程可以取数据去处理。 * * 当前版本: cobra 1.05 * 作 者: 关中刀客 * E-Mail : guanzhongdaoke@gmail.com * Blog : http://guan-zhong-dao-ke.blog.163.com/ * 完成时间: 2008年04月28日 */ #include "../common/Header.h" #include <sys/epoll.h> #include <sys/socket.h> #include <pthread.h> #include <semaphore.h> class EpollerEvent; class Epoller { public: /* 需要监听的套接字Epoller消息 */ enum EPOLLERMESSAGE { EPOLLERREAD, EPOLLERWRITE }; private: int m_epoller; // epoller句柄 pthread_mutex_t m_lock; // 中间队列的锁 pthread_cond_t m_cond; // 条件变量锁 sem_t m_sem; // 主轮循等待线程处理的信号量 Queue<EpollerEvent, EmptyLock> m_queue; // 中间的数据结构缓冲队列 public: Epoller(); ~Epoller(); public: /* 初始化epoller queuesize : 初始化的时候我们的缓冲队列默认的大小 number : 处理的数目 */ bool init_epoller(size_t queuesize, size_t number); /* 向epoller注册套接字需要监听事件 sock : 指定的套接字 iMsg : 注册到Epoller上的消息 pEvent : 指定的事件数据体 */ bool register_epoller_socket_event(SOCKET sock, int iMsg, EpollerEvent* pEvent); /* 改变Epoller中套接字监听的事件 sock : 指定的套接字 iMsg : 注册到Epoller上的消息 pEvent : 指定的事件数据体 */ bool change_epoller_socket_event(SOCKET sock, int iMsg, EpollerEvent* pEvent); /* 删除Epoller中套接字的所有事件 */ void delete_epoller_socket_event(SOCKET sock, int iMsg); /* 向Epoller发送指定的事件 pEvent : 指定的事件结构体 通常情况下,我们使用这个函数控制各Epoller线程的退出 类似于windows下的PostQueuedCompletionStatus */ void post_event_to_epoller(EpollerEvent* pEvent); /* 得到Epoller中的事件结构体数据 pEvent : 表示得到的数据体 一般情况下,这个函数由各Epoller线程函数调用,然后回得到指定的事件, 然后根据事件的信息去处理 类似于windows下的GetQueuedCompletionStatus */ bool get_event_from_epoller(EpollerEvent* pEvent, size_t timeout); /* 单独线程来循环Epoller主循环,检测套接字的事件 timeout : 超时的时间 */ int listen_epoller_event(int timeout); /* 销毁epoller */ void destroy_epoller(); }; extern Epoller g_Epoller; #endif 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-05-03
你就扯吧,nginx, lighttpd都是用epoll的高性能单进程单线程服务器,建议你阅读一遍C10K,搞搞清楚怎么实现高性能服务器。
|
|
返回顶楼 | |
发表时间:2008-05-03
theone 写道 你就扯吧,nginx, lighttpd都是用epoll的高性能单进程单线程服务器,建议你阅读一遍C10K,搞搞清楚怎么实现高性能服务器。 那你错了,epoll比poll的好处就是它可以直接的定位到是那个socket有时间,poll相对于select就是突破限制。如果是单线程的,可以很清楚的知道,你的事件处理recv,write和逻辑处理花费远大于你的epoll_wait,所以没有什么大的优势。另外,nginx, lighttpd都是用epoll的高性能单进程单线程服务器???他们真的很高性能吗? |
|
返回顶楼 | |
发表时间:2008-05-03
关中刀客 写道 theone 写道 你就扯吧,nginx, lighttpd都是用epoll的高性能单进程单线程服务器,建议你阅读一遍C10K,搞搞清楚怎么实现高性能服务器。
那你错了,epoll比poll的好处就是它可以直接的定位到是那个socket有时间,poll相对于select就是突破限制。如果是单线程的,可以很清楚的知道,你的事件处理recv,write和逻辑处理花费远大于你的epoll_wait,所以没有什么大的优势。另外,nginx, lighttpd都是用epoll的高性能单进程单线程服务器???他们真的很高性能吗? 上次那谁介绍的一个HTTP proxy,用单线程+event机制实现的 达到10G bps |
|
返回顶楼 | |
发表时间:2008-05-03
seen 写道 关中刀客 写道 theone 写道 你就扯吧,nginx, lighttpd都是用epoll的高性能单进程单线程服务器,建议你阅读一遍C10K,搞搞清楚怎么实现高性能服务器。
那你错了,epoll比poll的好处就是它可以直接的定位到是那个socket有时间,poll相对于select就是突破限制。如果是单线程的,可以很清楚的知道,你的事件处理recv,write和逻辑处理花费远大于你的epoll_wait,所以没有什么大的优势。另外,nginx, lighttpd都是用epoll的高性能单进程单线程服务器???他们真的很高性能吗? 上次那谁介绍的一个HTTP proxy,用单线程+event机制实现的 达到10G bps 其实看怎么应用了,如果都是简单的短连接,就是访问之后,server把对应的文件发挥给客户端,这样子的话,如果是iocp的话,在io线程直接发送也很不错,如果是epoll的话,我感觉epoll+线程池来说的话,按照我的思想,应该也不错吧,好吧,等等我把这个实现后,发一个简单的库给大家,大家自己测测勘 |
|
返回顶楼 | |
发表时间:2008-05-03
关中刀客 写道 theone 写道 你就扯吧,nginx, lighttpd都是用epoll的高性能单进程单线程服务器,建议你阅读一遍C10K,搞搞清楚怎么实现高性能服务器。
那你错了,epoll比poll的好处就是它可以直接的定位到是那个socket有时间,poll相对于select就是突破限制。如果是单线程的,可以很清楚的知道,你的事件处理recv,write和逻辑处理花费远大于你的epoll_wait,所以没有什么大的优势。另外,nginx, lighttpd都是用epoll的高性能单进程单线程服务器???他们真的很高性能吗? nginx是可以单台物理服务器并发5万个连接同时处理,性能不下降的,你说性能高不高?多线程用在context switch上面的开销太大,你根本撑不了5万个线程切换。 还是建议你看C10K的论文:http://www.kegel.com/c10k.html |
|
返回顶楼 | |
发表时间:2008-05-03
多线程就得有锁了,有锁有时候比较麻烦。
|
|
返回顶楼 | |
发表时间:2008-05-03
我什么时候说是需要那么多线程了?
思路和iocp一样,难道在使用iocp时创建那么多线程? |
|
返回顶楼 | |
发表时间:2008-05-05
关中刀客 写道 简单说就是你每次的epoll_wait所花费的时间,相对于你得到事件后所作的read,write==花费的时间要少狠多,至少我感觉是这样子的。
epoll_wait 返回说某个 socket 有可读,或者可写事件,这个时候进行 read/write 操作,花费的时间应该不多,实际做的操作应该是从 kernel 的 buffer 中 copy 数据到 应用程序的 buffer ,或者反过来。 真正耗时的操作应该是对具体事务的处理。比如对于一个 login 的操作,epoll_wait 返回说 socket 上有数据可读了,应用程序读入 client 传过来的 username/password ,然后到数据库中去查找对应的 username ,并且检查 password 是否匹配。最耗时的操作应该是在查数据库这一个步骤。 如果实际的事务处理耗费的时间很少,那么使用单线程来做就可以了,比如 memcached 。当然,现在 memcached 也支持多线程了,但主要的考虑是为了充分利用多 CPU 。 |
|
返回顶楼 | |
发表时间:2009-01-12
不同的设计适合不同的场景,不同的需求,没有固定的招式。不过单线程的服务器明显无法利用多核机器的CPU资源。
我想大家讨论问题时首先要统一一个场景才行。 |
|
返回顶楼 | |