一、 概述
在当今网络应用中,各种开源服务器可谓遍地开花。Web服务器如 Apache、AOL-Server、Lighttpd等;数据库服务器如:Mysql、PostgreSQL;MTA服务如Postfix、 Sendmail、Qmail等;HTTP代理服务器有Squid、Oops等。每一类服务器的设计都比较复杂且相关性较强,它们所用的服务器框架通用性不够,很难提炼出来,形成相对独立的服务器框架,供程序员快速开发自己的项目。在我们习惯了JAVA、.NET、PHP等快速开发带给我们的快乐时,却逐渐地远离的程序设计的本质,结果是知其然面不知所以然。好的开发框架及开发工具固然大大提高了软件生产率,但却容易使程序员浮于表面,无法深入,当需要设计开发更加高效、安全的服务器程序时,令很多人一愁莫展。
本文讲述了以Postfix(http://www.postfix.org/)的服务器框架为基础的半驻留进程池服务器的设计模式,经过本人整理,将其纳入ACL库中,做为ACL基础库中进程池服务器框架部分的核心。如果你非常熟悉 Postfix的框架设计,那么本节的内容对于你来说非常容易接受,当然,如果你未曾接触过postfix,也没关系,通过本文,你可以非常方便快捷地创建基于高级服务器框架之上的应用服务器程序:简单、高效、安全、可扩展性好等。
二、ACL进程池服务器框架概述
开发CGI程序、用过 inetd/xinetd的技术人大概应知道,自己所写的程序少有网络通信过程,基本上所有的IO操作都是基于标准IO(stdin, stdout, stderr)进行的,一切来得是那样简单,因为后台的服务器框架程序(如开发CGI时用的Apache)帮我们处理了复杂的网络通信过程。ACL的进程池服务器框架进行开发也是如此,但是提供了更大的灵活性,同时更加高效。ACL进程池服务器框架有如下特点:
a、用户直接与网络连接进行网络通信操作,但操作的接口是经过ACL库封装的更加灵活、丰富的函数接口;
b、进程池是动态可调的,只需在配置文件中设置进程池中的最大进程数,则ACL进程框架便自动根据应用负载情况调整工作进程数量;
c、进程池中的工作进程是半驻留的(这也是Postfix进程池的一大特色),当网络负载较高时,进程池中的每个工作进程可能都在工作,负载逐渐下降时,进程池中的工作进程并不立即退出,而是要空闲一段时间至超时,在超时之前又有新的会话连接到达时,其中的一个空闲进程便被服务器框架唤醒处理新连接,如果某些工作进程在超时时依然未接到新的处理任务则会自动退出。这便是半驻留进程池的特点:并不一直驻留内存等待新任务。这种设计的好处是:任务负载高时,进程池中的每个工作进程在处理完上一个任务可以立即处理新的任务,这样大大降低了创建新进程的开销;当任务负载较低时,工作进程在空闲一定时间后便自动退出,从而降低了资源浪费,同时也尽量避免了开发人员的应用程序本身的一些内存泄漏隐患(当然,开发人员应尽量避免内存泄漏问题);
d、半驻留的进程池有多种控制条件使工作进程处于半驻留状态:空闲时间、任务处理最大上限等;
ACL进程池服务器框架有一个后台守护进程(acl_master),该进程处于长驻留状态,监听着其所管理着的工作进程的对外服务的所有端口。当有新的客户端连接到达时,acl_master并不具体处理该连接,而是创建一个新的工作进程或“让”处于空闲状态的工作进程接管该连接并进行处理。acl_master与半驻留进程池中的工作进程之间是管理与被管理的关系,同时又是一种协作关系,因为acl_master并不象真正的操作系统那样可以任意调度哪个工作任务(大多通过中断进行任务时间片的分配),acl_master没有那种权限功能;在进程池中没有工作进程或进程池中的所有进程都处于忙碌状态时,如果整个进程池中工作进程的数量未超过配置中规定的最大值,acl_master便会创建新的工作进程来处理新到任务;当进程池中有空闲工作进程而又有新连接到达时,则acl_master知道有空闲进程存在,所以不会插手任务处理过程,此时,进程池中的空间工作进程阻塞在某一个 accept() 调用(或某一个锁)上,这时由操作系统具体将该新到连接分配给某一个工作进程,该工作进程便通知acl_master自己目前已处于忙状态,于是 acl_master便在其所维护的工作进程池的表中标记该工作进程的状态为忙状态。
小结,ACL进程池服务器框架应由两部分组成:acl_master后台守护管理进程与半驻留式工作进程池。acl_master负责任务分配及工作进程池的管理与维护;工作进程池中的工作进程负责具体的客户端连接请示与任务处理。
三、ACL进程池服务器所支持的工作进程框架模板
因为ACL的进程池服务器框架模型是基于Postfix进行修改的,所以首先大家需要知道原Postfix的工作进程框架模板有哪些被ACL所采纳。
a、single模板:该工作进程框架为开发者提供了开发服务器程序的函数接口,它的特点是每个工作进程在同一时刻最多仅能处理一个客户端连接;
b、multi模板:它的特点是每个工作进程可以同时处理多个并发连接,当然开发者在用此接口时需要在网络IO操作中采取非阻塞的方式,以免造成某工作进程在阻塞地读一个连接的数据时,而延迟了对其它网络连接的处理过程,从而造成性能上的极大降低;
c、trigger模板:它的特点是定时触发一个工作任务,可以把它与UNIX下的CRON功能相类比。
除以工作进程框架模板外,另外还增加了其它两个与线程池相结合的工作进程框架模板,如下:
a、listener模板:该模板允许与线程池相结合,从而使一个工作进程可以同时处理多个连接,而每个连接则由该进程内线程池的某个线程进行处理(目前已不继续开发了);
b、ioctl模板:该模板是listener模板的进一步改良,使工作进程与工作线程池结合的更加紧密,直接在工作进程的模板内嵌入了工作线程池句柄。
d、aio模板,将异步IO处理过程嵌入至工作进程模板中,从而更加高效地处理大并发网络连接的情况,其事件触发机制采用类型于squid, lighttpd, ircd 等类似的非阻塞服务器的模式。
四、使用ACL进程池服务器框架
有时为了让他人明白自己所讲的话,演讲人总会因唯恐别人不明白而特意讲得罗罗嗦嗦,岂不知此时观众已经被给绕晕至昏昏欲睡了,哈,但愿阁下看了以上长篇累牍的描述后依然保持头脑清醒,精神抖擞。OK,下面让我们从实例入手,看看怎样用ACL进程池框架编写自己的应用服务器程序。
a、编译并发布ACL进程池服务器框架
首先,需要编译acl_master守护进程,其实很简单,只需要如下步骤即可:
cd acl_project/; make all; make install
则在 acl_project/dist/master/libexec/linux32(以32位LINUX为例) 目录下生成 acl_master 可执行程序
cd dist/master; chmod 755 setup.sh; ./setup.sh /opt/acl
则在 /opt/acl/ 目录下存在如下目录:
libexec 目录:该目录下存放了 acl_master 程序及其它与具体应用相关的工作进程程序;
conf 目录:该目录下存放了 acl_master 的配置文件 main.cf 及工作进程程序的配置文件的存放目录 service/ ;
var 目录: 该目录下有两个了目录 log (存放日志的位置) 及 pid (存放运行进程进程号的位置),同时该 var 目录又是ACL进程池服务框架的默认运行路径;
sbin 目录:该目录下仅有两个比较简单的启动与停止脚本,它们来控制整个ACL进程池服务的启动与停止过程。
b、编写你的工作进程代码并发布,参考 快速创建你的服务器程序--single进程池模型;
c、修改配置文件、启动与停止整个进程池框架。
五、ACL进程池服务器框架配置说明
ACL进程池服务器框架有自己的配置文件格式及命名规范,它是你正确使用ACL进程池框架不可或缺的一部分,ACL进程池构架的开发者及维护者应熟练掌握这些格式与规范。下面就这些文件格式及命名规范一一说明。
5.1)main.cf 配置文件
该文件为 acl_master 守护进程的主配置文件,目前常用的配置项的含义如下:
daemon_directory:指定用户所写的工作进程可执行程序的存入目录,acl_master 会在该路径下搜索工作进程程序;
log_file:acl_master 的日志文件全路径名;
config_directory:工作进程程序的配置文件存放目录,acl_master 会读取该目录下所有有效的配置文件中并分析所有以 master_ 开头的配置项,注:以 master_ 开头的配置项为保留配置项的命名规范;
queue_directory:acl_master 进程及所有的工作进程的运行时所在路径;
pid_file:acl_master 进程的进程号的存储文件。
5.2)工作进程的配置文件
在 config_directory 所指的目录下,存放着各个工作进程的配置文件,acl_master 会首先读取该配置进行分析,与 acl_master 相关的配置项的含义如下:
master_disable:acl_master 是否要启动该工作进程所提供的对外服务(即是否会监听该配置文件中指定的监听端口),变量值有两个,yes 或 no。yes: 禁止该服务工作进程提供的服务;no:允许启动该服务工作进程;
master_service:服务工作进程所监听的地址及端口,格式为:[ip:]port,如:127.0.0.1:30080, :30080, 30080;
master_type:网络服务类型,目前一般为 inet 类型;
master_maxproc:服务工作进程的最大进程数;
master_command:服务工作进程的程序名,如果 master_disable 的配置内容为 no,则 acl_master 会在 main.cf 中 daemon_directory配置项指定的目录下搜索 master_command 配置项指定的服务工作进程程序名;
master_log:该服务工作进程的日志文件名;
以下的配置与工作进程各个框架模板相关的配置项,以 xxx_开头,其中,xxx 可以为:single,multi,trigger, listener,ioctl, aio。下面以 single_server 工作进程框架模板为例进行说明:
single_use_limit:服务工作进程处理事务的次数,如果为0则表明该服务工作进程长驻留内存,一直提供服务;如果大于0,则当该服务工作进程处理事务的次数达到此值后会自动退出;
single_pid_dir:服务工作进程的进程号的存放路径;
single_queue_dir:服务工作进程的运行路径;
single_rw_timeout:服务工作进程进行IO操作的超时时间,单位为秒;
single_buf_size:服务工作进程进行IO操作时所用的 ACL_VSTREAM 库函数的缓存大小;
除了以上的保留的配置项外,用户可以定义自己的配置项于该配置文件中,然后通过参数传递由服务器模板获得自己所要的参数。
个人微博:http://weibo.com/zsxxsz
acl 库的下载地址:http://www.sourceforge.net/projects/acl/
github:https://github.com/acl-dev/acl/
QQ 群:242722074
国内镜像:http://git.oschina.net/acl-dev/acl
在当今网络应用中,各种开源服务器可谓遍地开花。Web服务器如 Apache、AOL-Server、Lighttpd等;数据库服务器如:Mysql、PostgreSQL;MTA服务如Postfix、 Sendmail、Qmail等;HTTP代理服务器有Squid、Oops等。每一类服务器的设计都比较复杂且相关性较强,它们所用的服务器框架通用性不够,很难提炼出来,形成相对独立的服务器框架,供程序员快速开发自己的项目。在我们习惯了JAVA、.NET、PHP等快速开发带给我们的快乐时,却逐渐地远离的程序设计的本质,结果是知其然面不知所以然。好的开发框架及开发工具固然大大提高了软件生产率,但却容易使程序员浮于表面,无法深入,当需要设计开发更加高效、安全的服务器程序时,令很多人一愁莫展。
本文讲述了以Postfix(http://www.postfix.org/)的服务器框架为基础的半驻留进程池服务器的设计模式,经过本人整理,将其纳入ACL库中,做为ACL基础库中进程池服务器框架部分的核心。如果你非常熟悉 Postfix的框架设计,那么本节的内容对于你来说非常容易接受,当然,如果你未曾接触过postfix,也没关系,通过本文,你可以非常方便快捷地创建基于高级服务器框架之上的应用服务器程序:简单、高效、安全、可扩展性好等。
二、ACL进程池服务器框架概述
开发CGI程序、用过 inetd/xinetd的技术人大概应知道,自己所写的程序少有网络通信过程,基本上所有的IO操作都是基于标准IO(stdin, stdout, stderr)进行的,一切来得是那样简单,因为后台的服务器框架程序(如开发CGI时用的Apache)帮我们处理了复杂的网络通信过程。ACL的进程池服务器框架进行开发也是如此,但是提供了更大的灵活性,同时更加高效。ACL进程池服务器框架有如下特点:
a、用户直接与网络连接进行网络通信操作,但操作的接口是经过ACL库封装的更加灵活、丰富的函数接口;
b、进程池是动态可调的,只需在配置文件中设置进程池中的最大进程数,则ACL进程框架便自动根据应用负载情况调整工作进程数量;
c、进程池中的工作进程是半驻留的(这也是Postfix进程池的一大特色),当网络负载较高时,进程池中的每个工作进程可能都在工作,负载逐渐下降时,进程池中的工作进程并不立即退出,而是要空闲一段时间至超时,在超时之前又有新的会话连接到达时,其中的一个空闲进程便被服务器框架唤醒处理新连接,如果某些工作进程在超时时依然未接到新的处理任务则会自动退出。这便是半驻留进程池的特点:并不一直驻留内存等待新任务。这种设计的好处是:任务负载高时,进程池中的每个工作进程在处理完上一个任务可以立即处理新的任务,这样大大降低了创建新进程的开销;当任务负载较低时,工作进程在空闲一定时间后便自动退出,从而降低了资源浪费,同时也尽量避免了开发人员的应用程序本身的一些内存泄漏隐患(当然,开发人员应尽量避免内存泄漏问题);
d、半驻留的进程池有多种控制条件使工作进程处于半驻留状态:空闲时间、任务处理最大上限等;
ACL进程池服务器框架有一个后台守护进程(acl_master),该进程处于长驻留状态,监听着其所管理着的工作进程的对外服务的所有端口。当有新的客户端连接到达时,acl_master并不具体处理该连接,而是创建一个新的工作进程或“让”处于空闲状态的工作进程接管该连接并进行处理。acl_master与半驻留进程池中的工作进程之间是管理与被管理的关系,同时又是一种协作关系,因为acl_master并不象真正的操作系统那样可以任意调度哪个工作任务(大多通过中断进行任务时间片的分配),acl_master没有那种权限功能;在进程池中没有工作进程或进程池中的所有进程都处于忙碌状态时,如果整个进程池中工作进程的数量未超过配置中规定的最大值,acl_master便会创建新的工作进程来处理新到任务;当进程池中有空闲工作进程而又有新连接到达时,则acl_master知道有空闲进程存在,所以不会插手任务处理过程,此时,进程池中的空间工作进程阻塞在某一个 accept() 调用(或某一个锁)上,这时由操作系统具体将该新到连接分配给某一个工作进程,该工作进程便通知acl_master自己目前已处于忙状态,于是 acl_master便在其所维护的工作进程池的表中标记该工作进程的状态为忙状态。
小结,ACL进程池服务器框架应由两部分组成:acl_master后台守护管理进程与半驻留式工作进程池。acl_master负责任务分配及工作进程池的管理与维护;工作进程池中的工作进程负责具体的客户端连接请示与任务处理。
三、ACL进程池服务器所支持的工作进程框架模板
因为ACL的进程池服务器框架模型是基于Postfix进行修改的,所以首先大家需要知道原Postfix的工作进程框架模板有哪些被ACL所采纳。
a、single模板:该工作进程框架为开发者提供了开发服务器程序的函数接口,它的特点是每个工作进程在同一时刻最多仅能处理一个客户端连接;
b、multi模板:它的特点是每个工作进程可以同时处理多个并发连接,当然开发者在用此接口时需要在网络IO操作中采取非阻塞的方式,以免造成某工作进程在阻塞地读一个连接的数据时,而延迟了对其它网络连接的处理过程,从而造成性能上的极大降低;
c、trigger模板:它的特点是定时触发一个工作任务,可以把它与UNIX下的CRON功能相类比。
除以工作进程框架模板外,另外还增加了其它两个与线程池相结合的工作进程框架模板,如下:
a、listener模板:该模板允许与线程池相结合,从而使一个工作进程可以同时处理多个连接,而每个连接则由该进程内线程池的某个线程进行处理(目前已不继续开发了);
b、ioctl模板:该模板是listener模板的进一步改良,使工作进程与工作线程池结合的更加紧密,直接在工作进程的模板内嵌入了工作线程池句柄。
d、aio模板,将异步IO处理过程嵌入至工作进程模板中,从而更加高效地处理大并发网络连接的情况,其事件触发机制采用类型于squid, lighttpd, ircd 等类似的非阻塞服务器的模式。
四、使用ACL进程池服务器框架
有时为了让他人明白自己所讲的话,演讲人总会因唯恐别人不明白而特意讲得罗罗嗦嗦,岂不知此时观众已经被给绕晕至昏昏欲睡了,哈,但愿阁下看了以上长篇累牍的描述后依然保持头脑清醒,精神抖擞。OK,下面让我们从实例入手,看看怎样用ACL进程池框架编写自己的应用服务器程序。
a、编译并发布ACL进程池服务器框架
首先,需要编译acl_master守护进程,其实很简单,只需要如下步骤即可:
cd acl_project/; make all; make install
则在 acl_project/dist/master/libexec/linux32(以32位LINUX为例) 目录下生成 acl_master 可执行程序
cd dist/master; chmod 755 setup.sh; ./setup.sh /opt/acl
则在 /opt/acl/ 目录下存在如下目录:
libexec 目录:该目录下存放了 acl_master 程序及其它与具体应用相关的工作进程程序;
conf 目录:该目录下存放了 acl_master 的配置文件 main.cf 及工作进程程序的配置文件的存放目录 service/ ;
var 目录: 该目录下有两个了目录 log (存放日志的位置) 及 pid (存放运行进程进程号的位置),同时该 var 目录又是ACL进程池服务框架的默认运行路径;
sbin 目录:该目录下仅有两个比较简单的启动与停止脚本,它们来控制整个ACL进程池服务的启动与停止过程。
b、编写你的工作进程代码并发布,参考 快速创建你的服务器程序--single进程池模型;
c、修改配置文件、启动与停止整个进程池框架。
五、ACL进程池服务器框架配置说明
ACL进程池服务器框架有自己的配置文件格式及命名规范,它是你正确使用ACL进程池框架不可或缺的一部分,ACL进程池构架的开发者及维护者应熟练掌握这些格式与规范。下面就这些文件格式及命名规范一一说明。
5.1)main.cf 配置文件
该文件为 acl_master 守护进程的主配置文件,目前常用的配置项的含义如下:
daemon_directory:指定用户所写的工作进程可执行程序的存入目录,acl_master 会在该路径下搜索工作进程程序;
log_file:acl_master 的日志文件全路径名;
config_directory:工作进程程序的配置文件存放目录,acl_master 会读取该目录下所有有效的配置文件中并分析所有以 master_ 开头的配置项,注:以 master_ 开头的配置项为保留配置项的命名规范;
queue_directory:acl_master 进程及所有的工作进程的运行时所在路径;
pid_file:acl_master 进程的进程号的存储文件。
5.2)工作进程的配置文件
在 config_directory 所指的目录下,存放着各个工作进程的配置文件,acl_master 会首先读取该配置进行分析,与 acl_master 相关的配置项的含义如下:
master_disable:acl_master 是否要启动该工作进程所提供的对外服务(即是否会监听该配置文件中指定的监听端口),变量值有两个,yes 或 no。yes: 禁止该服务工作进程提供的服务;no:允许启动该服务工作进程;
master_service:服务工作进程所监听的地址及端口,格式为:[ip:]port,如:127.0.0.1:30080, :30080, 30080;
master_type:网络服务类型,目前一般为 inet 类型;
master_maxproc:服务工作进程的最大进程数;
master_command:服务工作进程的程序名,如果 master_disable 的配置内容为 no,则 acl_master 会在 main.cf 中 daemon_directory配置项指定的目录下搜索 master_command 配置项指定的服务工作进程程序名;
master_log:该服务工作进程的日志文件名;
以下的配置与工作进程各个框架模板相关的配置项,以 xxx_开头,其中,xxx 可以为:single,multi,trigger, listener,ioctl, aio。下面以 single_server 工作进程框架模板为例进行说明:
single_use_limit:服务工作进程处理事务的次数,如果为0则表明该服务工作进程长驻留内存,一直提供服务;如果大于0,则当该服务工作进程处理事务的次数达到此值后会自动退出;
single_pid_dir:服务工作进程的进程号的存放路径;
single_queue_dir:服务工作进程的运行路径;
single_rw_timeout:服务工作进程进行IO操作的超时时间,单位为秒;
single_buf_size:服务工作进程进行IO操作时所用的 ACL_VSTREAM 库函数的缓存大小;
除了以上的保留的配置项外,用户可以定义自己的配置项于该配置文件中,然后通过参数传递由服务器模板获得自己所要的参数。
个人微博:http://weibo.com/zsxxsz
acl 库的下载地址:http://www.sourceforge.net/projects/acl/
github:https://github.com/acl-dev/acl/
QQ 群:242722074
国内镜像:http://git.oschina.net/acl-dev/acl