`
zsxxsz
  • 浏览: 451064 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多

一、概述

      之前写过几篇有关如何使用 acl 的服务器框架编写网络服务器程序的文章(如:协作半驻留式服务器程序开发框架),现在总结一下,简要说明一下 acl 中所支持的几种服务器模型。acl 服务器框架支持四种模式:非阻塞模型、进程池模型、线程池进程混合模型,以及触发器模型。这四种服务器模型基本覆盖了我们编程时的常见模式,其中的进程池模型(对应于 Postfix 中的 single_server 方式)与触发器模型(对于 Postfix 中的 trigger_server 方式)移植于 Postfix,非阻塞模型、线程池进程池混合模型由笔者编写。本文结合 acl 库,不仅指明了服务器编程的方式,同时从实践角度讲述了在进行服务器编程时应该注意的事项。

 

二、五种服务器模型

      1、进程池模型:这是在 UNIX 上进行服务器编程时早期常用的方式,一般是每个 TCP 网络连接对应一个服务子进程,优点是安全、稳定,因为一个子进程 Down 掉仅影响一个 TCP 连接,同时,各个子进程之间的内存由系统进行隔离,可以在一定程度上避免数据泄露;缺点也很明显,就是并发连接数不能太高,毕竟进程资源是操作系统的宝贵资源,同时如果进程之间需要共享数据,操作起来也是一件棘手的事。早期的 UNIX 服务器程序并未采用进程池方式,而是来一个 TCP 连接请求临时启动一个子进程,处理完请求后子进程便退出,这种方式的效率是最低的,因为操作系统创建进程的开销还是比较昂贵的,象大家所熟知的 telnetd, ftpd, xinetd 等服务器程序都是这 种方式(CGI程序作为服务端也是这种方式);

      后来出于对性能的要求,便出现了进程池模型,而进程池模型又可分为:固定进程数量的进程池模型、动态变化的进程池模型,固定数量的进程池模型编程比较容易,但扩展性较差,动态进程池则更灵活,可以按需要创建进程,同时维持进程池的最小空闲进程数及最大进程数(象 Apache 的进程池模型有多个控制参数,分别表示预先启动进程数、最小空闲数、最大空闲数以及最大进程数;而 Postfix 的进程池则是半驻留进程池方式,限定的子进程的空闲时间及最大子进程数量,没有预先分配的策略;acl 中的进程池基于 Postfix,并在此基础上增加了预分配策略)。

      2、触发器模型:UNIX 系统管理员经常会使用 cron 系统服务来执行一些定期的任务,但系统 cron 存在一个问题,就是当时间间隔设置的较短时,如果定时任务处理时间超过了 cron 中设置的时间间隔,则就会产生任务处理过程重叠的问题(需要通过互斥等手段来避免此问题),因为 cron 任务是基于时间点触发的;而 Postfix 的触发器模型是基于时间间隔触发的,同时可以限定同时处理任务的进程数量,这就避免了 cron 方式下任务过程重叠的问题。

      3、非阻塞模型:高并发、非阻塞是这些年来高性能服务器的一种时髦语,这种方式一般是一个进程维护一个事件循环(采用 select/poll/epoll/kqueue/devpoll/iocp 等系统调用),采用多路复用方式,使单个进程可以支撑非常高的并发连接,因为网络通讯本身是有延迟的,采用非阻塞方式,则服务进程不会阻塞于任何 TCP 连接,哪个连接有数据就处理哪个,所以它可以处理很高的并发连接请求;但这种模型也有一个缺陷,就是一个非阻塞进程往往只能使用一个 CPU,这并不符合当今多核时代的要求(除了一个核之外,其它核都很空闲),象 squid、ircd 都是这种使用单核 CPU 的非阻塞代表,经常被人诟病,当然并非所有的非阻塞程序都是这样,象 nginx 处理的要好些,nignx 可以启动多个服务进程,每个进程是一个单独的非阻塞过程。

      在 acl 中的非阻塞模型默认采用与 nginx 相似的作法,可以启动多个非阻塞子进程,这即达到了高并发的目的,又可以充分利用多核,但它也有一个小缺点,就是分配给每个子进程的 TCP 连接并不均匀;另外,acl 的非阻塞模型还支持一个子进程由多个线程组成,每个线程是一个独立的非阻塞过程,这种方式姑且称之为多线程非阻塞进程池模型,它的优点是可以保证每个子进程内部线程池中的 TCP 连接分配是均匀的,但这种模型也有一个显著的缺点,当并发连接数高且内存分配比较频繁时,处理性能与线程池中线程数量是成反比的,原因并不是因为 CPU 核不够,而是因为在调用系统的 malloc/free 函数时,多个线程产生了大量的锁碰撞,导致性能下降,在 acl 中为了解决这个问题,专门有一个线程局部内存池,这个内存池可以从很大程度上避免系统全局内存锁碰撞, 当 CPU 核心越多,线程数越多时,整体性能则越高。

      非阻塞模型还有一个缺点,当用户使用此模型编程时,如果内部有 BUG,则在处理一个 TCP 连接的数据时进程崩溃了,则属于该进程的所有 TCP 任务都无法完成;所以,采用非阻塞编程的复杂度是较高,也容易出错,尤其是当产生了大量的函数嵌套递归时更是容易出错,acl 的非阻塞框架有多种措施防止因嵌套而产生的错误,但用户在实际使用时仍需小心谨慎。

      4、线程池进程池混合模型:顾名思义,就是多个服务子进程组成进程池方式,而每个子进程本身又是由线程池组成的,每个线程处理一个 TCP 连接,这种方式相比纯粹进程池的好处是可以有效地提高并发量、提高系统性能,同时可以使线程池中的多个线路之间共享数据变得比较容易;当然,相对于纯进程池模型,该模型的稳定性会有所降低,当用户基于此模型编写的程序有 BUG 时,会因为线程池中一个线程的崩溃而导致整个子进程退出,从而影响了多个 TCP 连接(当然不会影响其它子进程中的线程)。

      acl 的线程池进程池混合模型可以说是纯粹的进程池模型与非阻塞模型的折中模型:相对于纯粹进程池模型,该模型可以有效地提供并发数(甚至可以实现半非阻塞或全阻塞过程);同时相对于非阻塞模型,编程更为容易,不易出错。

      5、网络协程模型:该模型采用协程方式,将阻塞IO模式在底层转变为非阻塞模式,这样既可以象编写多线程一样简单,又可以象非阻塞程序一样高效,从而使技术人员快速地编写出高并发、高性能的网络服务程序。

 

三、服务器编程注意事项

      在进行服务器编程,有几个方面是需要注意的,如下:

      1、安全问题:在 UNIX 下编写的程序运行时尽量以普通用户身份运行,禁止以 root 运行,这样可以有效地防止因应用程序本身的漏洞而使黑客攻陷整个系统;acl 的服务器的配置文件中需要指定 master_args = -u 配置项,同时还需要配置:

      1.1)进程池模型:single_owner=xxx (xxx代表某个普通用户,如 nobody)

      1.2)触发器模型:trigger_owner=xxx

      1.3)非阻塞模型:aio_owner=xxx

      1.4)线程池进程池混合模型:ioctl_owner=xxx

      2、进程空闲退出机制:为了避免服务子进程有轻微的内存泄露或避免内存数据泄露,acl 采用半驻留方式,即当每个子进程空闲一段时间或处理一定 TCP 请求次数后子进程主动退出,为此,需要修改配置如下:

      2.1)进程池模型:single_use_limit=请求次数、single_idle_limit=进程空闲秒数

      2.2)触发器模型:trigger_use_limit=处理次数、trigger_idle_limit=进程空闲秒数

      2.3)非阻塞模型:aio_use_limit=处理次数、aio_idle_limit=进程空闲秒数

      2.4)线程池进程池混合模型:ioctl_use_limit=处理次数、ioctl_idle_limit=进程空闲秒数

      3、最大进程池限制:为了防止因用户编程失误而导致分配了大量的进程,使操作系统资源耗尽,acl 中通过配置限制了每种服务器模型的所启动的最大进程数量,配置统一为:master_maxproc=子进程最大数量(对于混合模型,配置项 ioctl_max_threads=每个子进程中最大线程数控制子进程中半驻留线程池的线程数)。

      4、服务子进程崩溃延迟启动机制:当用户编写的服务器程序如果频繁地崩溃,为了防止造成大量的 fork 操作,acl 的服务器控制程序(acl_master)的配置文件中的配置选项(service_throttle_time=子进程崩溃延迟启动秒数)可以达到延迟启动有问题子进程目的。

      5、日志功能:acl 的服务器框架采用 acl 库中统一的日志记录方式(可支持 syslog-ng),这样便于收集用户服务程序的运行状态。

      6、子进程崩溃通知机制:因为大部分服务器程序都是在后台运行的,某个程序崩溃后又会被 acl 的 控制程序(acl_master)启动,虽然 acl_master 的日志中会记录子进程崩溃的时间等信息,但我们毕竟不能一直盯着日志,为了解决此问题,编写了一个与 acl_master 配合的程序 acl_notify (在 acl/samples/master/acl_notify 目录下),可以接收来自于 acl_master 的消息,将服务子进程崩溃的消息以邮件或短信方式主动通知系统维护人员。

 

四、为什么事件引擎没有采用 libevent 等库

      原因很简单:

      1、Postfix 本身的事件引擎设计的就非常不错(acl 中的事件引擎是在此基础上改造的);

      2、libevent 是线程不安全的(原来的版本是不安全的,现在的版本不知如何);

      3、使用 libevent 无疑增长了 acl 框架库的依赖性,造成用户使用上的不便;

      4、acl 中的事件引擎功能更加强大:不仅支持 libevent 所支持的 select/poll/epoll/kqueue/devpoll,而且还支持 windows 平台下的 iocp、基于窗口的异步消息;

      5、acl 中的事件引擎与 acl 中的网络通信库结合的更为紧密。

 

      个人微博:http://weibo.com/zsxxsz

      原文地址:http://zsxxsz.iteye.com/blog/1563561

      acl 库下载:https://sourceforge.net/projects/acl/

      github: https://github.com/acl-dev/acl

      QQ 群:242722074

 

4
3
分享到:
评论

相关推荐

    网络与服务器编程框架库

    在高并发环境下,服务器框架库常常支持异步编程模型,比如使用回调、事件驱动或者Promise(如JavaScript的ES6特性)、协程(如Python的asyncio库)。异步编程可以避免阻塞,提高系统资源利用率,从而提升服务器处理...

    Linux高性能服务器编程高清原版PDF+源码

    《Linux高性能服务器编程》是一本深受IT从业者喜爱的经典著作,主要涵盖了如何利用Linux操作系统进行高效、稳定且可扩展的服务器程序开发。这本书深入探讨了Linux系统编程的核心概念和技术,为读者提供了丰富的实践...

    acl框架库是一个C语言网络框架库,主要包含:服务器开发框架、同步异步网络通讯、常用数据结构、进程池线程池、流式xmljson

    ACL框架库是一个专为C语言设计的网络框架,它提供了丰富的功能,使开发者能够更高效地构建网络应用程序。这个框架的核心特性包括...学习和掌握ACL框架,将有助于提升C语言网络编程的能力,提高开发效率和代码质量。

    acl.2.1.2.8.src.2012.7.2.zip_ACL_ACL_http_http json_协议

    通过ACL库,开发者可以快速构建出高性能、可扩展的网络服务,同时,由于其提供的各种工具和组件,使得网络编程变得更加简洁和高效。无论是对于新手还是经验丰富的程序员,ACL都是一个强大的开发资源。

    acl project

    2. **服务器框架**:服务器框架是构建高效服务的基础,ACL项目提供的服务器框架可能包含事件驱动模型、工作线程模型等设计,用于处理大量并发请求。它通常包括请求解析、处理逻辑、响应生成等功能,并能根据需求扩展...

    acl project 2008.9

    在服务器编程中,同步通信模式会导致线程阻塞,等待I/O操作完成,这会浪费大量资源。而异步通信允许线程在等待I/O操作期间继续处理其他任务,提高了服务器的并发处理能力。例如,非阻塞I/O、事件驱动模型(如Epoll)...

    acl-master.zip

    跨平台网络通信与服务器开发框架;...支持线程池、协程、进程池、非阻塞、触发器等多种服务器编程模型;支持 XML/JSON/MIME/BASE64/UUCODE/QPCODE/RFC2047 等常见格式编解码;还有其它更多有价值的功能。

    Windows安全性编程

    书中介绍了Windows 2000安全机制的核心内容,包括Kerberos、SSL、任务对象、新的ACL模型、COM+以及II5.0,同时说明了Windows 2000和Windows NT中安全机制的主要区别。 作者有着非常丰富的开发经验,写作本书的...

    Java服务器程序设计

    第3部分 java服务器编程[/font] [/font] 第5章 servlet包介绍[/font] [/font] 5.1 javax.servlet包[/font] 5.1.1 接口servlet[/font] 5.1.2 接口servletconfig[/font] 5.1.3 接口servletcontext[/font] 5.1.4 接口...

    文件服务器—终结保存

    2. **多线程/异步处理**:为了处理多个并发请求,服务器通常需要进行多线程或多进程编程,或者使用异步IO模型。 3. **数据库集成**:可能使用关系型数据库(如MySQL)或NoSQL数据库(如MongoDB)来存储和检索文件元...

    代理服务器源码

    1. **多线程技术**:为了处理多个并发的客户端请求,代理服务器通常会采用多线程或者异步I/O模型。多线程使得每个请求可以在独立的线程上下文中执行,避免了请求之间的相互等待,提高了服务器的响应速度和并发处理...

    FTP客户端与服务器的源代码

    5. **并发处理**:服务器需要处理多个客户端的并发请求,可能使用多线程、事件驱动编程或异步I/O模型。 在VC++中,你可以利用MFC(Microsoft Foundation Classes)库或WinAPI来实现FTP客户端和服务器。MFC提供了...

    简单代理服务器源码 c++

    8. **安全考虑**:代理服务器可能会暴露在公网中,因此需要考虑安全问题,比如防止DDoS攻击、实施访问控制列表(ACL)等。 了解以上技术后,我们就可以开始编写C++代理服务器的源码了。代码通常会包含以下部分:...

    一个基于C++实现的完整进行FTP应用管理的 Server服务器源码例子

    服务器需要维持一个循环来处理并发连接,可能需要使用多线程或者异步I/O模型来提高性能。 FTP协议本身由一系列命令构成,如`USER`、`PASS`、`CWD`、`LIST`、`RETR`和`STOR`等。在C++代码中,我们需要解析这些命令,...

    MQTT Server服务器源代码

    IOCP(I/O完成端口)是Windows系统中的一种高效网络编程模型,特别适合处理大量并发连接。IOCP利用操作系统的异步I/O机制,将I/O操作的完成通知与实际处理工作分离,从而提高服务器的并发性能。在MQTT Server中,...

    LINUX系统分析与高级编程技术(完整版)

    此外,还将涉及多线程编程、异步编程模型如epoll和 aio,以及程序调试技巧。 8. **设备驱动编程**:讲解Linux设备模型,如何编写字符设备驱动和块设备驱动,理解设备节点和设备文件系统。还会涉及USB、PCI等外设的...

    Unix高级编程

    10. **安全与权限**:介绍Unix的安全模型,包括用户和组、文件权限、访问控制列表(ACL)以及安全编程的最佳实践。 通过阅读《Unix高级编程》,开发者不仅能够提升Unix编程的技能,还能对操作系统内部机制有更深刻...

    MinIO 是一款开源的对象存储服务器

    4. **安全性**:MinIO提供了多种安全措施,包括SSL/TLS加密、访问控制列表(ACL)、服务器端加密(SSE)、多因素认证(MFA)以及数据完整性校验,确保数据在传输和存储过程中的安全。 5. **RESTful API**:MinIO...

    经典书籍:Lotus Domino R5 Web高级编程

    1. **Domino R5概述**:介绍Lotus Domino R5的基本架构,包括服务器、客户端、数据库和文档模型,以及其在Web环境下的工作原理。 2. **Web应用程序设计**:讲解如何利用Domino Designer进行Web应用的设计,包括表单...

    UNIX环境高级编程第二版

    4. **网络编程**:重点讲解了套接字(socket)编程,包括TCP/IP协议栈、UDP协议、套接字选项、服务器端与客户端编程模型等。 5. **文件系统接口**:探讨了文件和目录的操作,如打开、读写、关闭文件,以及符号链接...

Global site tag (gtag.js) - Google Analytics