进程服务器模型和线程服务器模型

来源:互联网 发布:阿里云香港主机连不上 编辑:程序博客网 时间:2024/05/21 14:58

 进程服务器模型和线程服务器模型

点击这里下载文件: 进程服务器模型和线程服务器模型.doc


服务器开发中模型的选择是决定程序运行的关键因素,最近开发的一个Linux下BT下载均衡器则抛弃了多线程模型,而采用了多进程模型,在不同的模型的选择过程中,自然涉及到了各自的优势和劣势。
多进程模型服务器具有以下特点:
  系统对立,功能清晰明显,可以同时启动多个进程,以提高系统的输出能力。
  系统需要处理好进程间数据共享问题。
多线程模型服务器具有如下特点:
  系统线程间数据共享方便,开发相对简单,而线程间互斥以及全局数据的互斥可能也是造成系统瓶颈的一个关键因素。
在网络服务器的开发过程中,参照木桶原理,系统的性能决定在瓶颈最大的那块木板上面。而在分析的过程中,网络IO部分无疑是那块最短的木板。

图一:典型的多线程服务器模型程序流程图
多线程服务器模型中,系统完成了初始化后,启动各自的线程,由全局队列保证各自的数据操作协调。伪数据结构及代码可以如下:
view plaincopy to clipboardprint?
  1. Class System{   
  2.   //接受客户端连接线程   
  3.   Static void AcceptThread();   
  4.   //数据操作线程,涉及到了socket的数据操作   
  5.   Static void DoDataThread();   
  6.   //辅助操作线程,比如数据库的缓存,批量入库等的   
  7.   Static void OtherThread();   
  8.   //保存客户端连接队列   
  9.   List<Client *> pLists;   
  10.   //数据库连接对象   
  11.   DBConnection dbConn;   
  12.   //全局服务器端socket   
  13.   Socket globalSock;   
  14.   //系统初始化   
  15.   Void Initial();   
  16.   //系统启动   
  17.   Void Start();   
  18.   //系统退出时清理资源   
  19.   Void Clean();   
  20. };   

如上伪代码阐述了多线程模型下,网络服务器开发的基本流程和数据结构相关。

图二:典型的多进程服务器模型UML时序图
合理的多进程调度管理程序应该根据当前负载压力情况,决定该启动的进程数量。

图三:典型进程服务器模型执行图
多进程的服务器程序涉及到了如下程序的开发:
  1:多进程调度服务器
  2:进程服务器
调度服务器负责接收网络请求,并将请求转化为进程服务器需要的格式,后通过进程间通讯发送到进程服务器程序,后采用进程间通讯获取处理结果,使用网络IO发送给客户端。
进程调度器在不同的平台上面处理方法可能不太一致:
  1:windows平台
    网络部分可以采用异步模式,如select或者IOCP。进程间通讯可以采用共享内存、SOCKET或者其他,视具体项目所要求的时间效率而定。
  2:Linux平台
    网络部分也采用异步模式,如select、/dev/poll、epoll。进程间通讯可以采用shm或者SOCKET之类。
  3:其他平台
    网络部分异步,如freebsd的kqueue。进程间通讯按照特定系统提供的最佳进程通讯而定。
调度服务器考虑采用单线程执行,讲网络IO封装成为事件驱动机制,这样避免了线程间的互斥以及线程数据之间的锁定带来的负荷,可以大大的提高整个系统的效率和伸缩性。
进程服务器使用进程间通讯模式,等待调度服务器发送来的特定数据,进行处理该数据,将结果再由进程间通讯方法发送给进程调度服务器。
按照进程服务器和调度服务器的部署方式不同,系统模型也会有很大的区别。如果进程服务器和调度服务器部署在同一台服务器上面,可以采用的进程间通讯方法就比较多,而且也比较方便快速,但是并不是特别适合集群以及系统压力分解。优点是系统性能可以达到最佳状态。
进程服务器和调度服务器部署在多台服务器上面的话,通讯的方式Socket为最佳。这种方式适合集群系统以及压力分解,缺点是系统的性能可能会较差。
对调度服务器的伪代码模型如下:
view plaincopy to clipboardprint?
  1. Class System{   
  2.   //保存进程列表   
  3.   List<Process *> pLists;   
  4.   //保存客户端列表   
  5.   List<Client *> pClients;   
  6.   Socket sock;   
  7.   Void Initial();   
  8.   Void Start();   
  9.   Void Clean();   
  10. }   

对象的主函数Start为系统关键函数:
伪代码如下:
view plaincopy to clipboardprint?
  1. Void Start(){   
  2.   //启动N个进程服务器   
  3. StartNProcess();   
  4.   //主线程循环   
  5.   While(flag){   
  6.     //获取Socket发生事件   
  7.     Event = GetClientEvent();   
  8.     Switch(event){   
  9.       //客户端连接事件   
  10.       Case ClientCome:   
  11.         //更新客户端队列   
  12.         UpdateClientList();   
  13.       //收到客户端数据   
  14.       Case GetClientData:   
  15.         //获取数据   
  16.         GetData();   
  17.         //分析处理数据   
  18.         ProcessData();   
  19.         //使用进程间通讯发送给某个进程   
  20.         SendToAProcess();   
  21.       //客户端离开   
  22.       Case ClientGoes:   
  23.          //更新客户端队列   
  24.         UpdateClientList();   
  25.       //客户端错误   
  26.       Case ClientError:   
  27.         UpdateClientList();   
  28.       //默认   
  29.       Default:   
  30.         DoSth();   
  31.      }   
  32.      //获取进程事件   
  33.      Event = GetProcessEvent();   
  34.      Switch(event){   
  35.       //进程处理完数据   
  36.       Case ParseData:   
  37.         //发送给客户端   
  38.         SendToClient();   
  39.       //错误   
  40.       Case Error:   
  41.         UpdateProcessList();   
  42.       Default:   
  43.         DoSth();   
  44.     }   
  45.     //进程队列处理   
  46.     PerformProcessList();   
  47.     //客户端队列处理   
  48.     PerformClientList();   
  49.   }   
  50. }   


从上面的伪代码中,我们可以大致了解到进程调度服务器所需要处理的工作。
  
  目前的WEB服务器apache可以通过配置文件的方式配置多种执行模式,包含:进程模式或者线程模式。
  另外由俄罗斯人开发的nginx web服务器以其极其优秀的性能,越来越受到大型运营商的青睐。而该服务器采用的就是进程服务器模型。通过配置多个PHP-FastCGI进程服务器程序,可以极大的提高动态web服务器的性能。

胡章优,吉林大学教师,博士,长春优狐科技开发有限公司总经理。专注于服务器开发,集群web服务器配置管理,系统安全配置,CDN网络架设以及机械电子控制系统开发。
个人博客:http://doserver.net

参考文献:
  进程服务器
  线程服务器
  Apache
  Nginx
  http://blog.codingnow.com/2006/10/multi_process_design.html

原创粉丝点击