池的概念
由于服务器的硬件资源“充裕”,那么提高服务器性能的一个很直接的方法就是以空间换时间,即“浪费”服务器的硬件资源,以换取其运行效率。这就是池的概念。池是一组资源的集合,这组资源在服务器启动之初就完全被创建并初始化,这称为静态资源分配。当服务器进入正式运行阶段,即开始处理客户请求的时候,如果它需要相关的资源,就可以直接从池中获取,无需动态分配。很显然,直接从池中取得所需资源比动态分配资源的速度要快得多,因为分配系统资源的系统调用都是很耗时的。当服务器处理完一个客户连接后,可以把相关的资源放回池中,无需执行系统调用来释放资源。从最终效果来看,池相当于服务器管理系统资源的应用设施,它避免了服务器对内核的频繁访问。
池可以分为多种,常见的有内存池、进程池、线程池和连接池。
内存池
内存池是一种内存分配方式。通常我们习惯直接使用new、malloc等系统调用申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。
内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。这样做的一个显著优点是,使得内存分配效率得到提升。
进程池和线程池
进程池和线程池相似,所以这里我们以进程池为例进行介绍。如没有特殊声明,下面对进程池的描述也适用于线程池。
进程池是由服务器预先创建的一组子进程,这些子进程的数目在 3~10 个之间(当然这只是典型情况)。线程池中的线程数量应该和 CPU 数量差不多。
进程池中的所有子进程都运行着相同的代码,并具有相同的属性,比如优先级、 PGID 等。
当有新的任务来到时,主进程将通过某种方式选择进程池中的某一个子进程来为之服务。相比于动态创建子进程,选择一个已经存在的子进程的代价显得小得多。至于主进程选择哪个子进程来为新任务服务,则有两种方法:
1)主进程使用某种算法来主动选择子进程。最简单、最常用的算法是随机算法和 Round Robin (轮流算法)。
2)主进程和所有子进程通过一个共享的工作队列来同步,子进程都睡眠在该工作队列上。当有新的任务到来时,主进程将任务添加到工作队列中。这将唤醒正在等待任务的子进程,不过只有一个子进程将获得新任务的“接管权”,它可以从工作队列中取出任务并执行之,而其他子进程将继续睡眠在工作队列上。
当选择好子进程后,主进程还需要使用某种通知机制来告诉目标子进程有新任务需要处理,并传递必要的数据。最简单的方式是,在父进程和子进程之间预先建立好一条管道,然后通过管道来实现所有的进程间通信。在父线程和子线程之间传递数据就要简单得多,因为我们可以把这些数据定义为全局,那么它们本身就是被所有线程共享的。
线程池主要用于:
1)需要大量的线程来完成任务,且完成任务的时间比较短。 比如WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大。但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
2)对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
3)接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。
进程城实现源码:
如何在Linux下实现进程池技术,原贴见:
http://topic.csdn.net/u/20090206/16/b424e1c1-90dc-4589-a63f-1d90ed6560ae.html。
-
- int main()
- {
- int iReLen;
- char szBuffer[64];
- ...
-
- InitProcessPoll();
- ....
- while(1)
- {
- iRelen = recv(iSock, szBuffer, sizeof(szbuffer), 0);
- if (iRelen > 0)
- {
- SubmitWork(szBuffer, iRelen);
- }
- }
- ...
- }
-
-
- int SubmitWork(void *pBuffer, int iMsgLen)
- {
- int iMsgQueID;
-
- iMsgQueID = GetMsgQue(key, 0);
-
- msgsnd(iMsgQueID, pBuffer, iMsgLen, 0);
- }
-
- int InitProcessPoll(const int iProcessNum)
- {
- int iPid;
-
-
- iPid = fork();
- if (iPid == 0)
- {
- InitMngProcess(iProcessNum);
- }
- return 0;
- }
-
- typedef struct
- {
- int pid;
- int iFlag;
- } T_ProcessStatus;
-
-
- T_ProcessStatus *pProcessMng = NULL;
-
-
- INT32 iMaxProcessNum = 0;
-
-
- InitMngProcess(const int iProcessNum)
- {
- int i;
- int iPid;
- int iRtn;
- int iMsgLen;
- int iMsgQue1, iMsgQue2;
- char szBuffer[64];
-
-
- pProcessMng = calloc(iProcessNum, sizeof(T_ProcessStatus))
-
- for (i = 0; i < iProcessNum; i++)
- {
- iPid = fork();
- if (iPid == 0);
- {
-
- ResourceProcess();
- }
- pProcessMng[i].pid = iPid;
- pProcessMng[i].iFlag = 0;
- }
-
- iMaxProcessNum = iProcessNum;
-
-
- iMsgQue1 = CreateMsgQue();
-
-
- iMsgQue2 = CreateMsgQue();
-
-
- signal(SIGUSR1, ReleaseAProcess);
-
-
- while(1)
- {
-
- iMsgLen = msgrcv(iMsgQue1, szBuffer, sizeof(szBuffer), 0);
-
-
- iRtn = msgsnd(iMsgQue2, szBuffer, iMsgLen, 0);
-
-
- NoticeAIdleProcess();
- }
- }
-
-
- int NoticeAIdleProcess()
- {
- int i;
-
- for (i = 0; i < iMaxProcessNum; i++)
- {
- if (pProcessMng[i].iFlag == 0)
- {
- pProessMng[i].Flag = 1;
- kill(processMng[i].pid, SIGUSR1);
- return 0;
- }
- }
-
- return -1;
- }
-
-
- void ReleaseAProcess(int iPid)
- {
- int i;
-
- for (i = 0; i < iMaxProcessNum; i++)
- {
- if (pProessMng[i].pid == iPid)
- {
- pProcessMng[i].iFlag = 0;
- return;
- }
- }
-
- return;
- }
-
-
- void ResourceProcess()
- {
-
- signal(SIGUSR1, SIG_IGN);
-
-
- sigprocmask()
- while(1)
- {
-
- pause();
-
-
- void StartWork()
-
-
- NoticeMngProcessFinishedWork();
- }
- }
-
-
- void StartWork()
- {
- char szBuffer[64];
- int iMsgID;
- int iRtn;
-
- iMsgID = msgget();
- iRtn = msgrcv(iMsgID, szBuffer, sizeof(szBuffer), 0);
-
-
-
- return;
- }
-
-
- void NoticeMngProcessFinishedWork();
- {
- kill(MngProcessPid, SIGUSR1);
-
- return;
- }
-
- int main()
- {
- int iReLen;
- char szBuffer[64];
- ...
-
- InitProcessPoll();
- ....
- while(1)
- {
- iRelen = recv(iSock, szBuffer, sizeof(szbuffer), 0);
- if (iRelen > 0)
- {
- SubmitWork(szBuffer, iRelen);
- }
- }
- ...
- }
-
-
- int SubmitWork(void *pBuffer, int iMsgLen)
- {
- int iMsgQueID;
-
- iMsgQueID = GetMsgQue(key, 0);
-
- msgsnd(iMsgQueID, pBuffer, iMsgLen, 0);
- }
-
- int InitProcessPoll(const int iProcessNum)
- {
- int iPid;
-
-
- iPid = fork();
- if (iPid == 0)
- {
- InitMngProcess(iProcessNum);
- }
- return 0;
- }
-
- typedef struct
- {
- int pid;
- int iFlag;
- } T_ProcessStatus;
-
-
- T_ProcessStatus *pProcessMng = NULL;
-
-
- INT32 iMaxProcessNum = 0;
-
-
- InitMngProcess(const int iProcessNum)
- {
- int i;
- int iPid;
- int iRtn;
- int iMsgLen;
- int iMsgQue1, iMsgQue2;
- char szBuffer[64];
-
-
- pProcessMng = calloc(iProcessNum, sizeof(T_ProcessStatus))
-
- for (i = 0; i < iProcessNum; i++)
- {
- iPid = fork();
- if (iPid == 0);
- {
-
- ResourceProcess();
- }
- pProcessMng[i].pid = iPid;
- pProcessMng[i].iFlag = 0;
- }
-
- iMaxProcessNum = iProcessNum;
-
-
- iMsgQue1 = CreateMsgQue();
-
-
- iMsgQue2 = CreateMsgQue();
-
-
- signal(SIGUSR1, ReleaseAProcess);
-
-
- while(1)
- {
-
- iMsgLen = msgrcv(iMsgQue1, szBuffer, sizeof(szBuffer), 0);
-
-
- iRtn = msgsnd(iMsgQue2, szBuffer, iMsgLen, 0);
-
-
- NoticeAIdleProcess();
- }
- }
-
-
- int NoticeAIdleProcess()
- {
- int i;
-
- for (i = 0; i < iMaxProcessNum; i++)
- {
- if (pProcessMng[i].iFlag == 0)
- {
- pProessMng[i].Flag = 1;
- kill(processMng[i].pid, SIGUSR1);
- return 0;
- }
- }
-
- return -1;
- }
-
-
- void ReleaseAProcess(int iPid)
- {
- int i;
-
- for (i = 0; i < iMaxProcessNum; i++)
- {
- if (pProessMng[i].pid == iPid)
- {
- pProcessMng[i].iFlag = 0;
- return;
- }
- }
-
- return;
- }
-
-
- void ResourceProcess()
- {
-
- signal(SIGUSR1, SIG_IGN);
-
-
- sigprocmask()
- while(1)
- {
-
- pause();
-
-
- void StartWork()
-
-
- NoticeMngProcessFinishedWork();
- }
- }
-
-
- void StartWork()
- {
- char szBuffer[64];
- int iMsgID;
- int iRtn;
-
- iMsgID = msgget();
- iRtn = msgrcv(iMsgID, szBuffer, sizeof(szBuffer), 0);
-
-
-
- return;
- }
-
-
- void NoticeMngProcessFinishedWork();
- {
- kill(MngProcessPid, SIGUSR1);
-
- return;
- }