一种具有可伸缩服务能力的高性能Web代理服务器
朱树人1, 2, 彭 妮1
(1. 长沙理工大学 计算机与通信工程学院, 湖南 长沙, 410076;
2. 北京航空航天大学 计算机学院, 北京, 100083)
摘要: 用非对称多进程事件驱动(AMPED)模型提高代理服务器高并发请求同步增长的可伸缩服务能力, 扩展了AMPED模型的代理服务功能。 同时, 给出了Web代理服务器关键模块的设计与实现。 该Web代理服务器定义了1个主进程, 6个helper进程, 其中2个helper 进程从磁盘上读文件的in ode信息, 4个helper 进程从磁盘上读文件的内容, 解决了I/O慢速处理和CPU快速处理之间的矛盾。 事件驱动模块采用回调函数解决并发请求和状态跳转的管理。 页面缓存模块采用自适应缓冲置换策略, 根据资源大小, 将大于阈值的资源按LRU 算法移走, 实现对页面的高效管理。 测试结果表明, 该web代理服务器在负载平均为9KB, 处理请求数能达到800个/s, 具有较强的并发请求处理能力。
关键词: 代理服务器; AMPED模型; 事件驱动; 可伸缩服务能力
中图分类号:TP393 文献标识码:A 文章编号: 1672-7207(2005)06-1064-05
A high performance Web proxy server with flexible service ability
ZHU Shu-ren1, 2, PENG Ni1
(1.College of Computer and Communication Engineering,
Changsha University of Science and Technology, Changsha 410076, China;
2. College of Computer, Beijing University of Aeronautics and Astronautics, Beijing 100083, China)
Abstract: Asymmetric multiprocess event driven (AMPED) model was used to improve the ability for Web proxy server to deal with hundreds of requests, and extend the proxy service functionality of AMPED. At the same time, the design and implementation of the important parts of this Web proxy server was designed and implemented. This proxy server defined a main process and six helper processes, among them two helper processes read in ode information of the files from the magnetic disc, four helper processes read the contents of the files from the magnetic disc. The event-driven part adopted callback function to finish processes management and state conversion, and the adaptive cache technology was applied to this proxy server, and the resources that are bigger than a certain value are removed based on LRU algorithm, according to the size of resources. The experiment results show that under the load of 9 KB in average, it can serve 800 requests per second, so this proxy server has high processing ability.
Key words: proxy server; AMPED model; event-driven; flexible service ability
Internet流量的指数级增长, 加大了网络传输的延迟、 Web服务器的压力和用户检索文档的响应时间[1]。 采用代理服务器缓存数据可以减少响应时间, 然而, 对于现行的代理服务器, 当高并发请求达到一定水平时, 其服务平台大都缺乏能跟随负载同步增长的可伸缩服务能力, 从而造成服务品质下降。 现行的代理服务器软件一般采用常规的多进程/进程池或多线程/线程池模型, 其性能比异步事件驱动模型的性能低, 所以, 实现基于异步事件驱动的高性能代理服务器成为当前研究热点。 在此, 作者采用非对称多进程事件驱动模型(AMPED)[2], 在SPED模型[3]的基础上增加helper 进程, 当主进程read ( )[4] 一块文件内容时, 若该文件内容不在文件Cache上而在磁盘上, 主进程就把磁盘访问任务交给helper 进程完成, 以解决I/O的慢速处理和CPU快速处理之间的矛盾。 在AMPED模型基础上, 采用回调函数管理并发请求和状态跳转, 设计并实现具有跟随负载同步增长的可伸缩服务能力的高性能Web代理服务器。
1 AMPED模型的代理服务功能扩展
1.1 Web代理服务器工作机制
Web代理服务器在Web用户和服务器之间起中继的作用, 从客户端来看它表现为1个服务器, 而对服务器来说它表现为1个客户端, 三者的具体关系如图1所示。

图 1 web代理服务器外部数据流
Fig. 1 The external dataflow of web proxy server
其具体工作过程为[5]:
a. 客户向代理服务器发出请求(请求某个网页)。
b. Web代理服务器接收客户请求, 解析此请求, 查找请求的网页是否在缓存中存在。
c. 如果请求的网页在缓存中没有查找到, 或者存在但已经失效, 那么, 代理服务器将请求转发给源服务器。
d. 源服务器接收请求并处理, 把响应发送给代理服务器。
e. 代理服务器接受到响应把它返回给用户。
f. 代理服务器检查此响应是否可以缓存, 如可以, 则保存到本地磁盘。
1.2 AMPED模型的代理服务功能扩展
Web服务中当高并发请求达到一定数量时, 服务请求转化成数目更大的I/O和网络请求, 需要消耗巨量的网络基础资源。 为了提高服务器性能, 必须解决I/O慢速处理和CPU快速处理之间的矛盾, 为此, 先后出现了以Apache为代表的多进程模型、 以Roxen[6]为代表的多线程模型、 以Zeus为代表的单进程事件驱动(SPED)模型、 以Flash为代表的非对称多进程事件驱动(AMPED) 模型等。
为了实现高性能的服务器、 服务巨量并发请求, 应采用事件驱动模型。 在Sped模型[7]中, 对文件句柄访问, 当访问的文件内容不在文件Cache而在磁盘上时, 会产生阻塞现象, 从而暂时挂起进程, 导致CPU空转。 对于代理服务器, 缓存的网页因为占较大的存储空间, 存储位置只能是在物理硬盘上, 从而造成大量的磁盘I/O操作, 所以, 采用AMPED模型。 图2给出了AMPED模型代理服务功能扩展, read( ) 的原型为ssize-t read (int filedes, void *buff , size-t nbytes)[8], 其中filedes是待读的文件句柄, buff是进程缓冲区, nbytes是待读文件内容的长度。 read( )既可以是非阻塞也可以是阻塞的。 当所读文件内容在文件Cache里(即在内存里)时, read( )是非阻塞的; 当所读文件内容不在文件Cache里而在磁盘上时, read( )是阻塞的。 在AMPED模型中增加helper[9, 10] 进程, 当主进程打算read( ) 一块文件内容, 若该文件内容不在文件Cache 而在磁盘上时, 主进程就把磁盘访问任务交给helper 进程完成。 当helper进程把文件内容读到内存后, 主进程再read( ) 该块文件内容。 这时, 由于文件内容已在文件Cache中, 主进程调用的read( )不会阻塞。

图 2 AMPED模型的代理服务功能扩展
Fig. 2 The extending part of proxy service function on AMPED
2 关键模块的设计与实现
2.1 事件驱动模块的设计与实现
服务器软件在访问网络或文件时的典型做法是使用阻塞式(blocking)I/O操作, 并采用多线程复用多个I/O通道。 这种方法的主要缺陷是当I/O通道数目很大时, 其性能严重下降, 系统缺乏良好的伸缩性。 另一种使系统伸缩性更好的方法是使用非阻塞式(non-blocking)I/O, 例如UNIX select()系统调用。 使用事件驱动模型和异步I/O技术的网络应用体系结构, 主要包含3个层次: 底层NIO, 异步通信子层和应用层。 每个层次里只有少量的组件。 在NIO层中, 核心的组件是可层次扩展的变迁NIO, 其输入输出弧代表与其上层之间的数据交换。 异步通信子层是一个适配层, 它只有一个核心组件aSocketQ, 这是一个队列, 所有与NIO和客户层之间的输入输出都缓冲在这个队列中并随后进行并处理。 与此类似, 客户层中也包含一个队列appQ, 它缓冲并处理来自客户应用程序和异步通信子层的所有输入和输出。 服务器在接受一个客户请求时, 该请求的服务最终映射为对CPU处理资源的使用和对I/O资源的使用。 从客户请求到资源使用的一对多映射是一个同步粒度细化的过程, 细化的结果是系统能更协调地使用资源, 减少性能瓶颈产生的机会和持续时间。 队列的作用是尽量吸收不能及时处理的请求, 而不是在资源不足时简单地拒绝服务。
在代理服务器中定义1个主进程和6个helper进程, 其中2个helper 进程从磁盘上读文件的inode信息, 4个helper 进程从磁盘上读文件的内容, 少量进程的切换减轻了操作系统的负担, 提高了系统效率。 当主进程read( )一块文件内容时, 首先对内存中存放的文件索引进行查找, 若查找的内容在索引中, 则主进程就把磁盘访问任务交给helper进程完成。 主进程向helper 进程每次只发送一个磁盘访问命令, 当helper 完成磁盘访问操作后, 向主进程返回一个完成消息[11], 主进程收到消息后发送下一个磁盘访问命令。 若查找内容不在索引中, 则主进程将发送代理服务请求到远程服务器, 请求服务。
2.1.1 回调函数
由于代理服务器只采用一个主进程, 主进程同时要处理多个请求, 在同一时刻这些请求可能处于请求处理过程的不同阶段(如图3所示), 需要把它们都管理起来时需要同时保留每个请求的处理状态, 事件驱动模块采用回调函数[12-15]解决并发请求和状态跳转的管理。 例如: 函数B(请求读取)向函数A(接收客户请求)传递其地址, 然后在A中发生某种事件(event)时, 通过从A里面传递过来的B的地址调用函数B, 通知B发生了什么事情, 让B做出相应反应。 把函数B称为回调函数(图4所示)。 通过这种回调函数的机制来实现处理过程的推进。

图 3 事件驱动模块
Fig. 3 Event-driven Module

图 4 回调函数示意图
Fig. 4 The Sketch map of callback function
2.1.2 回调函数的定义
回调函数是不能显式调用的函数, 通过将回调函数的地址传给调用者从而实现调用。 要实现回调, 必须首先定义函数指针:
void f( ); //函数原型
上面的语句声明了一个函数, 没有输入参数并返回void。 那么, 函数指针的声明方法为
void (*) ( );
左边圆括弧中的星号是函数指针声明的关键。 另外2个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数为空)。
在代理服务器中, 每个网络I/O是通过对应的文件描述符来管理, 根据select( )调用的特点, 将文件描述符的管理分为2个文件描述符集(读、 写集)以及两个回调函数管理数组来管理(读数组和写数组)。 每个文件描述符和与之关联的回调函数及其参数通过回调结构联系起来。 数据结构如下:
struct cb{
viod (*cb_fn)(void*); /*回调函数*/
viod *cb_arg; /*将传给回调函数的参数*/
}
static struct cb rcb [FD_MAX], wcb[FD_MAX]; /*回调函数管理数组*/
static fd_set rfds, wfds; /*文件描述符集*/
2.1.3 回调函数的注册
对等待事件的文件描述符提供事件处理回调函数, I/O调度根据注册的函数对I/O事件进行处理:
void cb_add(int fd, int write, viod(*fn)(void*), viod*arg)
{
struct cb *c;
c=&(write?wcb: rcb)[fd]; /*注册回调函数结构*/
c->cb_fn=fn;
c->cb_arg=arg;
}
2.1.4 回调函数的注销
在对一个文件描述符的事件处理完成后取消对此文件描叙符的处理, 调用注销回调函数:
void cb_free(int fd, int write)
{
struct cb *c;
c=&(write?wcb: rcb)[fd];
c->cb_fn=NULL; /*清空回调函数*/
c->cb_arg=NULL; /*清空回调函数参数*/
}
2.2 页面缓存模块的设计与实现
页面缓存模块采用自适应缓冲置换策略[15], 根据资源的大小, 将大于阈值的资源按LRU 算法移走, 有效地实现了对页面的高效管理。 算法描述如下:
a. 将大于当前阈值的资源按LRU算法移走, 直到大于当前阈值的资源全部被移走为止时, 转b.; 或若已有足够空间来缓冲新到来的资源文件, 则置换结束。
b. 缓冲区中剩余的资源文件仍按LRU算法移走, 直到有足够的空间来缓冲新到来的资源文件, 此时置换结束。
阈值确定步骤为: 首先设定初始阈值, 然后周期地调整此阈值。 若此时命中率比使用前一阈值时的缓冲区命中率高, 则同方向调整阈值, 否则, 反方向调整阈值, 以期获得更高的命中率。
缓冲管理策略实现中所用数据结构如下:
Struct Memory -cache {
Bool state ; / * 已缓冲为true , 否则为false */
Char * url -value ; / *请求的url 值* /
Char *access -time ; / * 访问的时间*/
Struct Memory -cache * prev ; / * 在缓冲区或辅助链表中的前驱* /
Struct Memory -cache *next ; / * 在缓冲区或辅助链表中的后继*/
Struct Memory -cache *hash -next ; / *指向哈希表中下一节点* /
Char file -data ; / * 指向缓冲区中数据的开始位置* /
Int total -length ; / *缓冲数据的总长度* /
}
3 测试与分析
对该代理服务器进行负载能力测试, 测试时间为10 min, 请求的目标网页的大小为9 Kb。 测试结果见表1。
表 1 负载能力测试表
Table 1 Load ability test at different process

从表1可以看出, 该web代理服务器对并发用户的支撑能力最大为同时200个连接, 具有较强的处理并发请求的能力。 在负载平均为9 Kb时的负载下, 能处理请求数能速度达到800个/s。
4 结 论
a. 采用非对称多进程事件驱动模型, 在事件驱动模块中通过回调函数管理并发请求和状态跳转, 设计并实现了具有与负载同步增长的可伸缩服务能力的高性能Web代理服务器。
b. 在Web代理服务器中定义1个主进程和6个helper进程, 较好地解决了I/O慢速处理和CPU快速处理之间的矛盾, 提高了系统效率。
c. 页面缓存模块采用自适应缓冲置换策略, 根据资源大小,将大于阈值的资源按LRU算法移走, 实现了页面的高效管理。
d. 该Web代理服务器在负载平均为9 Kb时, 处理请求数达到800 个/s, 具有较强的并发请求处理能力。
参考文献:
[1]Sherlia S T. Placing Servers in Overlay Networks[D]. Washington: Department of Computer Science, Washington University, 2002. 151-153.
[2]Vivek S P, Peter D, Willy Z. Flash: An efficient and portable Web server[A]. Proc of the USEN IX 2001 Annual Technical Conf, CA, 2001, 36(3): 66-70.
[3]Neil M. Web server performance and scalability[EB/OL]. http: //www. zeus. co. uk 2001-03-27.
[4]Rossi F. An event mechanism for Linux[J ]. Linux Journal, 2003, 25(7): 215-218.
[5]孙永辉. 姜昱明. HTTP代理服务器的实现[J]. 计算机工程与应用, 2003, 16(3): 172-174.
SUN Yong-hui, JIANG Hui-ming. Implementation of HTTP proxy server[J]. Computer Project and Applications, 2003, 16(3): 172-174.
[6]张兴明, 耿晨歌, 汪乐宇. 网络流媒体服务器的机制研究与实现[J]. 计算机工程与设计, 2004, 25(1): 61-64.
ZHANG Xing-ming, GENG Chen-ge, WANG Le-yu. Research on mechanism and implementation of network streaming-media-server[J]. Computer Engineering and Design, 2004, 25(1): 61-64.
[7] 段翰聪, 卢显良, 宋杰. 基于EPOLL的单进程事件驱动通信服务器设计与分析[J]. 计算机应用, 2004, 24(10): 36-39.
DUAN Han-cong, LU Xian-liang, SONG Jie. Analysis and design of communication server based on EPOLL and SPED[J]. Computer Applications, 2004, 24(10): 36-39.
[8]Douglas E C, David L S. Internetworking with TCP/IP, Vol III: Clinet-Server Programming and Applications Linux/POSIX Sockets[M]. Middlesex-somerest: Prentince International Hall InC, 2001. 89-99.
[9] 雷迎春, 李国杰. 基于ASPED模型的高性能Web服务器[J]. 计算机研究与发展, 2001, 38(7): 669-777.
LEI Ying-Chun, LI Guo-Jie. A high performance web server based on the ASPED model[J]. Journal of Computer Research & Development, 2001, 38(7): 669-777.
[10] Kenneth D R. Protocol Analysis[M]. Newyork: Springer West Net, 2002. 356-361.
[11]Cheng K, Kambayashi Y. Enhanced Proxy Caching with Content Management[M]. London: Springer Verlag London Ltd, 2002. 198-199.
[12]Lemon J, Kqueue. A generic and Scalable Event Notification Facility[A]. Yoonho P. Proceeding of the USENIX 2001 Annual Technical Conference[C]. Boston: Springer Massachusetts, 2001. 113-117.
[13] 盛大同, 霍耀森. 基于Linux的代理服务器的研究和实现[J]. 计算机工程与应用, 2003, 7: 124-125.
SHENG Da-tong, HUO Yao-sen. The research and implementation of proxy server under linux[J]. Computer Project And Application, 2003, 7: 124-125.
[14] 赵衍敏, 姚自明, 赵岳松. 基于HTTP协议的高速代理服务器[J]. 计算机工程与科学, 2003, 25(2): 64-66.
ZHAO Yan-min, YAO Zi-ming, ZHAO Yue-song. The implementation of a high-speed proxy server based on HTTP[J]. Computer Engineering & Science, 2003, 25(2): 64-66.
[15]李军峰, 姜昱明. 代理服务器上自适应缓冲资源一致性维护策略[J]. 西安电子科技大学学报(自然科学版), 2003, 30(5): 687-690.
LI Jun-feng, JIANG Yu-ming. Adaptive maintaining cache consistency on the proxy server[J]. Journal of Xidian University, 2003, 30(5): 687-690.
收稿日期:2005-05-10
基金项目: 湖南省自然科学基金资助项目(03JJY3102); 湖南省教育厅科学研究基金资助项目(05C247)
作者简介: 朱树人(1964-), 男, 湖南长沙人, 教授, 硕士生导师, 从事计算机网络与分布式系统研究
论文联系人: 朱树人, 男, 教授; 电话: 13308468898(手机); E-mail: zhusr@csust.edu.cn