`
关中刀客
  • 浏览: 26187 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

来说说epoll+线程池

阅读更多
最近在作学习epoll,也看了很多的资料,关于epoll的原理就不多说了,很简单,需要注意的是,如果仅仅的采用epoll来处理网络服务器的话,感觉性能不会提高太大,毕竟io的处理相对于epoll或者poll的检测来说,时间消耗是比较多的。这个话说得可能比较的绕口,简单说就是你每次的epoll_wait所花费的时间,相对于你得到事件后所作的read,write==花费的时间要少狠多,至少我感觉是这样子的。所以如果真的需要提升性能的话,就需要epoll+线程池,但是问题就是,这个线程池怎么做呢?很多朋友的线程池是可以自我调整的,当没有了就自动地分配。我的看法是这样子没有什么必要吧(自己对linux系统本身没有什么深的理解)。感觉仿照iocp就不错了,当然,仿照是不可能的,iocp实现很复杂的。我们模仿他的流程和机制,适当的损失些性能(只要就是事件通知机制)还是可以接受的。另外一个最大的问题就是我们还是要让操作系统来帮助我们在底层来排队,而不是自己在上层来实现排队,主要是因为处理肯定没有epol_wait产生的速度快,这样子会造成中间的缓冲队列一直增大的。所以还是留给操作系统来帮助我们排队吧。至少目前我的cobra_linux就是这样子实现的。

等有机会展示一下我的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
分享到:
评论
16 楼 mryufeng 2009-03-12  
epoll和select改进的地方在哪里 你们都没搞清楚在这里讨论 唉
15 楼 Magicloud 2009-01-15  
mikeandmore 写道
Magicloud 写道
Linux常用编程模型是多进程,无数服务、程序都是单线程的,如果连这个都不知道,就别讨论linux编程了。


well
实际上这不应该是个原因。
Linux上面没有官方的拒绝线程。但是linux不管线程还是进程都是clone出来的。
这点设计不是很好。所以很多保守的做法就是在linux下,尽量避免线程。
但是这并不是一个理由拒绝在linux下使用线程。

当然进程最稳定,但是进程所带来的空间开销不是永远可以容忍的。

linux对线程的支持远比windows复杂,没有“不管……都是……”一说。
常见说法“linux创建线程相对慢“是过去对轻量级进程的说法,现在过时了。
而进程的空间开销问题,linux早就做到重入了,共享data和code段不会导致重复浪费。
14 楼 mikeandmore 2009-01-14  
Magicloud 写道
Linux常用编程模型是多进程,无数服务、程序都是单线程的,如果连这个都不知道,就别讨论linux编程了。


well
实际上这不应该是个原因。
Linux上面没有官方的拒绝线程。但是linux不管线程还是进程都是clone出来的。
这点设计不是很好。所以很多保守的做法就是在linux下,尽量避免线程。
但是这并不是一个理由拒绝在linux下使用线程。

当然进程最稳定,但是进程所带来的空间开销不是永远可以容忍的。
13 楼 mikeandmore 2009-01-14  
sdh5724 写道
iunknown 写道
关中刀客 写道
简单说就是你每次的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 。



终于看到一个说正确的了。  一般来说, 会用一个线程专们用来读写数据。 多线程是为了处理业务。 如果又读数据, 又是做业务,还一个THREAD, 怎么也是不科学的。

如果仅仅考虑proxy的话,单线程就应该可以了吧。。

MS nginx就是这样nginx的worker process仅仅是为了均摊每个进程的IO负荷。。。。
不知道说的对不对。。。
12 楼 sdh5724 2009-01-13  
iunknown 写道
关中刀客 写道
简单说就是你每次的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 。



终于看到一个说正确的了。  一般来说, 会用一个线程专们用来读写数据。 多线程是为了处理业务。 如果又读数据, 又是做业务,还一个THREAD, 怎么也是不科学的。
11 楼 sdh5724 2009-01-13  
。。。。。。。。。。感觉到了上古时代。真不知道说什么好。
10 楼 Magicloud 2009-01-12  
Linux常用编程模型是多进程,无数服务、程序都是单线程的,如果连这个都不知道,就别讨论linux编程了。
9 楼 yiqingfeng 2009-01-12  
不同的设计适合不同的场景,不同的需求,没有固定的招式。不过单线程的服务器明显无法利用多核机器的CPU资源。
我想大家讨论问题时首先要统一一个场景才行。
8 楼 iunknown 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 。
7 楼 关中刀客 2008-05-03  
我什么时候说是需要那么多线程了?
思路和iocp一样,难道在使用iocp时创建那么多线程?
6 楼 七猫 2008-05-03  
多线程就得有锁了,有锁有时候比较麻烦。
5 楼 theone 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
4 楼 关中刀客 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+线程池来说的话,按照我的思想,应该也不错吧,好吧,等等我把这个实现后,发一个简单的库给大家,大家自己测测勘
3 楼 seen 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
2 楼 关中刀客 2008-05-03  
theone 写道
你就扯吧,nginx, lighttpd都是用epoll的高性能单进程单线程服务器,建议你阅读一遍C10K,搞搞清楚怎么实现高性能服务器。

那你错了,epoll比poll的好处就是它可以直接的定位到是那个socket有时间,poll相对于select就是突破限制。如果是单线程的,可以很清楚的知道,你的事件处理recv,write和逻辑处理花费远大于你的epoll_wait,所以没有什么大的优势。另外,nginx, lighttpd都是用epoll的高性能单进程单线程服务器???他们真的很高性能吗?
1 楼 theone 2008-05-03  
你就扯吧,nginx, lighttpd都是用epoll的高性能单进程单线程服务器,建议你阅读一遍C10K,搞搞清楚怎么实现高性能服务器。

相关推荐

    Linux系统下,使用“epoll+线程池”技术,通过makefile管理的简单项目-“服务器与客户端完成通信并处理小型业务”

    内容摘要:使用“epoll+线程池”技术,通过makefile管理的简单项目——“服务器与客户端完成通信并处理小型业务” 技术涉及:网络初始化、epoll模型、线程池、线程同步、互斥锁 适用人群:在校大学生,并对网络通信...

    epoll+线程池实现的高并发服务器

    epoll+线程池实现的高并发服务器

    Linux下Epoll+线程池的简单Web服务器

    本文将深入探讨如何在Linux环境下使用Epoll和线程池技术构建一个简单的Web服务器。这个Web服务器的实现是基于Linux内核提供的异步I/O模型,Epoll,以及线程池策略,以优化系统资源的使用和提高并发性能。 首先,让...

    C语言+epoll+线程池实现的聊天室.zip

    在本项目"C语言+epoll+线程池实现的聊天室"中,开发者采用了一种高效并发处理模型来构建一个实时交互的聊天平台。这里主要涉及三个关键的技术点:C语言编程、epoll事件管理机制以及线程池的运用。 首先,C语言是...

    Linux下使用EPoll+队列+多线程的C++实现

    在这个“Linux下使用EPoll+队列+多线程的C++实现”项目中,开发者使用了`epoll`来监听并管理TCP服务器的连接。`epoll`的工作流程大致如下: 1. **创建epoll句柄**:首先,通过`epoll_create()`函数创建一个epoll...

    Linux下基于epoll_线程池高并发服务器实现研究

    本文研究了基于 Linux 系统的高并发服务器实现,通过使用 epoll 机制和线程池技术来提高服务器的并发能力和实时性。以下是本文的知识点概述: 1. 客户机/服务器模式(Client/Server):客户机向服务器提出请求,...

    Linux下基于epoll 线程池高并发服务器实现研究.pdf

    其次,本文给出了基于epoll+线程池技术设计的高并发服务器详细算法,并提供了一个在Linux环境下用C语言编写的基于epoll和线程池技术的服务器和客户端实验程序,实现了服务器和客户端之间的并发通信,以及实验结果的...

    epoll+线程池

    Linux + C + Epoll实现高并发服务器,运用线程池技术。

    epoll 多线程 线程池

    线程池是一种线程使用模式,它预先创建了一组线程,当有任务需要执行时,从线程池中取出一个空闲线程来执行任务,完成后线程不被销毁,而是回到线程池中等待下一次任务分配。线程池可以控制系统的资源消耗,避免大量...

    epoll、线程池实现在线电子词典

    本项目"epoll、线程池实现在线电子词典"就是利用这两种技术来实现一个高效、稳定的服务端,能够处理大量来自客户端的查询请求。 epoll(Event Poll)是Linux内核提供的一种I/O多路复用机制,它允许单个进程监控多个...

    linux下服务器的搭建,socket+epoll模型+线程池+心跳检测+工厂模式;内含客户端的测试

    本教程将深入探讨如何利用socket编程、epoll模型、线程池、心跳检测以及工厂模式来搭建这样的服务器,并且提供了客户端的测试代码。以下是对这些知识点的详细解释: 1. **Linux Socket编程**: Linux Socket是进程...

    基于epoll与线程池的网络即时通讯系统

    在“9.10 epoll+线程池-聊天室”这个文件中,很可能是详细讲解了如何结合epoll和线程池来构建聊天室的源代码和实践案例。通过学习这部分内容,开发者可以深入理解这两种技术在实际应用中的结合方式,以及如何优化...

    Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)

    在Linux 系统下面用C 语言实现的高并发服务器的代码,具体用到了Epoll,线程池,数据库连接池。 具体可以看下连接http://blog.csdn.net/wuyuxing24/article/details/48758927

    epoll+多线程代码

    epoll+多线程的例子,本例子还有压力测试。

    基于C++使用 epoll + threadpool 实现的 webServer,支持GET、POST

    【作品名称】:基于C++使用 epoll + threadpool 实现的 webServer,支持GET、POST 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 ...

    linux socket NIO epoll教程参数讲解.zip

    大并发服务器编程模型 windows iocp完成端口模型可支持1万大并发,但是linux能作到5万大并发

    http_server.zip

    http_serverlinux下c语言版基于epoll+reactor模式的http文件下载服务器linux下c语言版基于epoll+reactor模式的http文件下载服务器linux下c语言版基于epoll+reactor模式的http文件下载服务器linux下c语言版基于epoll+...

Global site tag (gtag.js) - Google Analytics