Linux网络服务器性能比较的研究

来源:IT专家网 作者:IT专家网
  

据《硅谷》杂志2012年第22期刊文称,高性能网络服务程序在当前的linux环境下应用非常广泛,不论是主流web服务器,还是mmo服务器,都需要高性能的网络服务器结构提供支撑。就主流的linux网络服务器模型性能进行比较,得出一般性结论,为以后网络开发人员对网络服务器的选择提供一定的参考依据。

关键词:linux;服务器;性能;比较

1标准tcp客户端的设计

在客户端主程序中需要的一般参数包括服务器端ip地址,服务器端口,客户端fork形成的子进程数,子进程向服务器发送的请求连接数量以及要求服务器返回的数据字节数。据此给出客户端的基本模型:

for(i=0;i

if((pid=fork())==0){ //fork子进程

for(j=0;j

fd=connect(……);//建立到服务器的tcp连接

write(fd,request,strlen(request));//向服务器发送返回数

read(fd,reply,nbytes);//读返回的数据

Close(fd); //关闭套接字

客户端运行的命令可以如下:./client127.0.0.1888855004000

虽然有比较完整的基于benchmark的基准测试程序用于测试各种web服务器性能,但就一般性比较各服务器程序范式,使用上述客户端模型基本可以满足。

2Linux网络服务器分类

2.1常见服务器分类

传统意义上将服务器可以分为2种类型:循环服务器(iterativeserver)和并发服务器(concurrentserver)。这样分类虽然简单,但却不够细化。服务器的网络模型分类可根据以下依据:是不是以阻塞方式来处理请求,是不是多路复用和使用哪种多路复用函数(如select,poll,epoll);是不是采用多线程技术,线程间的关系该如何组织;是不是采用多进程,一般多进程的调用多是在accept函数前。根据此分类依据,可将服务器模型大体分为三大类:阻塞式模型、多路复用模型、实时信号模型。

2.2linux网络服务器模型分析

1)单线程处理,处理流程为:socket-->bind-->listen-->[accept-->read-->write-->close]-->close其中括号内为服务器循环。

2)为一个请求分配一个进程或是线程,主线程调用阻塞在accept处,每个新的连接请求到来,都实时为其生成线程处理其请求。但多数情况进程的线程数有限,创建线程的开销和过多线程后进行上下文切换的开销,对于真正的系统的设计,该模型只具有理论上的实用性,后面的实验也验证这点。

3)服务器端预派生一定数量进程或线程,让所有线程都阻塞在accept调用的地方。以前的观点认为大量进程或线程同时阻塞在accept处时,会产生“惊群”现象,即所有的线程或进程都被同时激活,但只有一个获取连接描述符并返回,其它线程或进程又转为睡眠。linux从2.2.9及以后的版本都不存在这个问题,只有一个会被激活。

4)Tcp预先派生进程服务程序,accept使用文件上锁或者线程上锁保护模型。一般线程锁一次只有一个线程可以阻塞在accept处。避免所有预产生的线程都直接阻塞在accept,可以避免惊群问题。而文件锁不具有通用性,将不参与模型性能比较。

5)主线程处理accept,预派生多个线程(线程池)处理连接。主线程在accept返回以后,将clientfd放入线程的消息队列,线程池将读取线程消息队列然后处理clientfd。这里主线程只对accept进行操作,快速返回后继续调用accept,有效的避免了拒绝连接的问题,当加大线程消息队列的长度时,可以显著减少消息队列处的系统调用频繁度。

3六种服务器模型的测试比较

3.1实验结果

客户端进程数用户时间(耗费在用户进程上的cpu时间(s))系统时间(内核在系统调用花费的时间(s))服务器发送字节数每个进程处理连接数为

1,迭代服务器

10(s)0.728045(s)40005000

20.0041.2400840005000

40.0042.4300840005000

100.020001(s)5.85637(s)40005000

150.0320028.9445640005000

100.69204345000

100.772048100005000

10.0280017.78449400050000

2,tcp并发服务器,每个客户一个子进程

102.0641340005000

1001.544094000500

20.0124.6082940005000

40.0320016.9764440005000

100.04800216.50140005000

10.10000521.3413400050000

3,tcp预先派生子进程,accept无上锁保护(最后一项为预派子进程数)

10.0040.8240514000500015

100.0160018.924564000500015

100.0080.61203840005002

100.0200015.89637400050002

1000.0240018.776554000500100

1000.0125.8163640005002

1000.0560036.73242400050020

(相比tcp并发服务器,处理时间缩短两至三倍,但预派子进程越多,性能有所下降)

4,tcp并发服务器,每个客户一个线程

10.0281.0040640005000

100.0121.284084000500

100.1680112.116840005000

可见性能稍优于进程并发

5,tcp预先派生线程池,每个线程各自accept

100.8560534000500010

100.0120.884055400050010

100.0640049.040574000500010

100.0600036.4724400050002

性能优于为每个客户创建一个线程,当预派线程变多时性能明显下降

6,tcp预先创建线程池,主线程统一accept

100.8760544000500010

1001.01206400050010

100.10000610.27664000500010

100.0360027.68848400050002

该模型性能稍逊于模型五,主要是该模型既需要互斥锁又需要条件变量。

3.2一般性结论

1)纵向比较

一,对于迭代服务器:客户进程数与系统处理时间成线性关系,处理相同的连接数,采用多进程的方式发送可以缩短30%~40%的时间。当连接数与进程数相同时,对于返回字节数多的链接,系统花费的时间会多一些,但不会根本上改变系统性能,服务器发送数据占系统处理时间的一小部分。

二,对于tcp并发服务器:虽然局部范围内连接数与系统处理时间的关系具有波动性,但总体仍然可以得出以下结论,对于总数相同的的连接,增大客户进程数可以缩短系统处理时间;

三,对于tcp预先派生子进程:当预派子进程数相同,客户进程数增大时,每个链接的平均系统处理时间会增加少许。对于当预派子进程数不同时,派生进程少的服务器可以明显降低系统处理时间,也就是说,预派子进程变多时,会增加系统负担,降低系统平均处理效率。

四,对于每个客户一个线程的tcp并发服务器:当总连接数相同,客户连接进程变多时,每次连接的平均时间会有一定增加。

五,tcp预先派生线程池,每个线程各自调用accept:当派生的线程数下降时,系统性能会有一定提高;相同的连接数,客户端进程变多时,每个连接的处理时间增加。

六,tcp预先创建线程池,主线程统一accept:每个客户进程发送的连接数相同,进程变多时,单个连接处理时间增加;连接总数相同,客户进程变多时,处理时间增加。

2)横向比较

平均时间比较:这里处理每个连接平均时间最短的是迭代服务器,这个结果是好多人都没想到的(究其原因是因为迭代服务器没有进程控制开销),第二好的是tcp预先创建线程池,主线程统一accept服务器模型,它与tcp预先派生线程池,每个线程各自accept服务器模型性能相当。第四是tcp并发服务器,每个客户一个线程服务器模型。第五是tcp预先派生子进程,accept无上锁保护服务器模型。最差的是tcp并发服务器。

4结束语

本文首先对客户模型进行设计,设计出一种通用客户模型。在此基础上列举出几种通用服务器模型,并就每种模型设计出服务器程序,对每一种模型进行性能测试。当今网络服务器所面对的客户数量增加的压力越来越大,而linux网络服务器又是主流的网络服务器平台,因此设计出高性能的服务器模型是每个从事linux网络编程人员的心愿。测试所用数据都经过仔细筛选,对实际应用系统的设计具有很高的参考价值。


时间:2013-02-26 10:43 来源:IT专家网 作者:IT专家网 原文链接

好文,顶一下
(0)
0%
文章真差,踩一下
(0)
0%
------分隔线----------------------------


把开源带在你的身边-精美linux小纪念品
无觅相关文章插件,快速提升流量