异步IO框架

烽驿2009开源实时通信平台 源码获取:svn checkout http://fy2009.googlecode.com/svn/trunk/ fy2009-read-only

 

大型通信服务器通常要处理成千上万的并发用户,如果采用同步IO方式处理用户数据收发,意味着需要为每个用户创建一个甚至两个线程(一个接收线程,一个发送线程)。 同步IO的优点是编程简单,当用户数比较少(比如几个,最多几十个)时,这样做是可以接受的,但对于成千上万的用户,创建如此众多的线程是不可想象的。在任何一个时间点,始终保持每个CPU(对于多核CPU也可以说一个核)刚好有一个活动线程,系统处理能力将被最大化。考虑到每个线程总有等待IO的时刻(非活动状态),通常粗略地认为线程数是CPU数量的两倍时系统处理能力最佳。总之,线程数并非越多越好,这是刚开始学习多线程编程的人需要特别注意的。实际上线程过多不仅不能提高系统性能,频繁地线程切换反而引起系统性能下降。因此,大型可伸缩(Scalable)通信服务器几乎无一例外地采用异步IO方式处理网络数据收发。异步IO机制使通信服务器可以更灵活地设计其线程模型,可以选择单线程,也可以选择线程数可配置的线程池或其它多线程方案。但不幸的是,异步IO通常意味着复杂的状态机管理,会大大增加软件的复杂性,因此,设计实现一个大型可伸缩通信服务器向来不是一件容易的事,远远不是搞定几个Socket函数调用那么简单。
下面将阐述本项目所采用的异步IO框架,并将在后续的博克中分别讲述其基于实时信号(Real-Time Signal)--http://blog.csdn.net/DreamFreeLancer/archive/2009/07/27/4383193.aspx,EPOLL(http://blog.csdn.net/DreamFreeLancer/archive/2009/07/28/4387375.aspx)和完成端口(Completion Port)-- http://blog.csdn.net/DreamFreeLancer/archive/2009/07/31/4398758.aspx等的实现。
操作系统提供的异步IO服务基本上可以分成两大类:
可用通知型(Availability Notification)
即当IO设备(如Socket)上当前有数据等待接收,或发送缓冲区不满,允许发送数据时,操作系统将以一定方式通知用户程序。Linux下的实时信号和EPOLL,以及Linux或Windows下的各类Select,Poll等都属于这一类。
完成通知型(Completion Notification
用户程序开始并不关心当前的IO设备状况,只是根据自身需要决定是否提交一个异步接收或发送请求到某IO设备,操作系统并不保证该操作立即成功,但会在该操作实际完成时通知应用程序。Windows下的完成端口属于这一类。
无论上述哪种异步IO模型,其共同点是对IO设备状态的监测与报告,本异步IO框架着眼于该共同点,提供统一的IO状态监测与报告服务,并对不同线程模型有着良好的适应性。
该异步IO框架以Linux下实时信号和EPOLL等广泛采用的可用通知型异步IO机制作为参考模型,进行适当调整,以适应完成通知型异步IO的需要。
主要接口定义及框架实现如下:
异步IO事件处理接口--应用程序实现该接口以接收异步IO事件。
class aio_event_handler_it : public lookup_it

{

public:
 
     virtual void on_aio_events(int32 fd, uint32 aio_events, pointer_box_t ex_para=0)=0;

};

参数:fd,事件相关的Socket描述符; aio_events: IO事件,允许一次传递多个事件(相互间按位与),EPOLL中会有这种情况,实时信号和完成端口中,一次只有一个事件; ex_para: 用于传递其它扩展的事件参数,其类型pointer_box_t
是一长度足够容纳一个指针的整型,对于32位操作系统,其长度应是32位,64位系统则为64位。在完成端口实现中,该参数用于传递OVERLAPPED指针。

异步IO服务访问点接口--受理或取消指定Socket描述符上的异步IO服务申请,并绑定异步IO事件处理器,当IO事件发生时,事件处理器的on_aio_events方法将被调用
class aio_sap_it : public lookup_it

{

public:

   //为支持灵活的线程模型,直接受理服务申请的对象未必是最终的服务提供者(aio_provider_t,后面会介绍),可能

   //只是驻留在线程局部存储(TLS)中的服务代理(aio_proxy_t,后面会介绍),由服务代理受理服务申请时,必需

   //由下面的参数dest_sap指定最终服务提供者,否则,该参数为NULL; sp_aioeh_t是上面aio_event_handler_it

   //的Smart Pointer  
   virtual bool register_fd(aio_sap_it *dest_sap, int32 fd, sp_aioeh_t& eh)=0;

          
   virtual void unregister_fd(int32 fd)=0; 

};

异步IO服务提供者aio_provider_t--实现aio_sap_it接口,提供直接或间接的异步IO服务申请(注册),当应用程序(aio_event_handler_it实现者)和aio_provider_t的“心跳线程”(后面给出解释)在同一线程中时(如附图https://p-blog.csdn.net/images/p_blog_csdn_net/dreamfreelancer/EntryImages/20090726/aio-1.JPG所示),应用程序通过直接调用该服务提供者的aio_sap_it注册异步IO服务; 反之, 应用程序通过调用aio_proxy_t的aio_sap_it接口完成服务申请,后者再调用服务提供者的同名接口完成间接服务申请。aio_provider_t还实现了heart_beat_it接口,应用程序通过在“心跳线程”中循环驱动该接口为异步IO服务提供“动力”,监测已登记Socket描述符上的异步IO事件,并调用绑定的aio_event_handler_it将事件通知应用程序。aio_provider_t可在Linux和Windows间移值; 为实时信号,EPOLL和Widnows下的完成端口提供尽可能一致的访问接口。

aio_provider_t并没有被实现成Singleton,因此,同一进程中根据需要创建多个provider实例,分别管理各自的Sockets是允许的,它们当然可以有不同的“心跳线程”。但彼此间不应该有过多的逻辑耦合。

异步IO代理aio_proxy_t--实现aio_sap_it接口,当应用程序线程需要从aio_provider_t的“心跳线程”之外申请异步IO服务时(如附图https://p-blog.csdn.net/images/p_blog_csdn_net/dreamfreelancer/EntryImages/20090726/aio-2.JPG所示),需通过该代理对象申请服务。该代理驻留在应用程序线程局部存储(TLS)中。通过该代理对象申请异步IO服务时,用户事件处理对象(实现了aio_event_handler_it接口),将被注册到该代理对象中,另外再自动生成一个实现了aio_event_handler_it接口的“存根对象”(aio_stub_t),并将后者注册到aio_provider_t的心跳线程中,当“存根对象”收到IO事件时,通过高效的oneway_pipe_t(http://blog.csdn.net/DreamFreeLancer/archive/2009/06/01/4231151.aspx)将事件跨线程送给aio_proxy_t, 代理对象找到注册的用户事件处理器,并在应用程序线程中调用其aio_event_handler_it接口。
总之,aio_provider_t接合aio_proxy_t和aio_stub_t,提供了通用,灵活,可移植的异步IO服务框架。有关该框架基于实时信号,EPOLL和完成端口的一些实现细节,将在后续博克中说明。

 

重要参数:

static sp_aiop_t aio_provider_t::s_create(uint16 max_fd_count=AIO_DEF_MAX_FD_COUNT, bool rcts_flag=false); 

max_fd_count参数影响系统的并发容量, 缺省值是1024,就是说通过该服务管理的IO设备(或Socket)不能超过这个数,否则,将出错。显然,对于大于通讯服务器,这个值偏小,初始化aio_provider对象时,需指定一个足够大的值,最大当然不超过65535,那是操作系统的上限。对于Windows系统,该值也不能太小,不能小于512(实际精确值应是488,详细原因参:http://blog.csdn.net/DreamFreeLancer/archive/2009/07/09/4335571.aspx),否则,该服务将完全不能工作。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值