Reactor and Proactor

引言:
   这里准备记录一下自己对TCP服务器的高性能设计模式的理解!

系统IO分为:阻塞型,非阻塞同步型,非阻塞异步型

阻塞型IO:拿read方法来举例,现在系统的一个线程调用了read方法,这时控制权只有等到read调用结束后才会回到这个线程手里(调用read函数的代码就会一直停留在那里,直到它所处理的socket缓存中有数据来)。这时这个调用者(此线程)就被阻塞了,这其中的这段时间,这个线程做不了任何其他的事情。

非阻塞同步型IO:同样是read。现在系统的一个线程调用了read方法,这时控制权会立即返回到这个线程手里(此线程不会一直停留在那里)。这时线程的业务逻辑会得到两种结果,第一:调用成功;第二:返回错误或者当前资源不可用,等一下或者等会再试一次。read函数的话,如果当前处理的socket没有数据可以读取,则立即返回,告诉调用者:现在还没有数据,等会再试。

非阻塞异步型IO:这种形式和非阻塞同步型IO的不同之处在于:调用者(线程)在调用函数时:调用函数在立即返回的同时,还告诉调用者,这次请求已经开始了,系统会使用其他的资源或者是线程来完成此次调用操作,并会在完成后告知调用者(回调函数)。

下面理解一下两种模式:Reactor and Proactor
    在理解这两种模式之前,先看一个名词:事件分享器。事件分享器的作用是:将那些读写事件源分发给各个读写事件的处理者,我们开发人员在开始的时候需要在事件分享器中注册那些感兴趣的事件,并提供相应的处理者或者是回调函数,事件分享器在适当的时候会将事件分发给到处理者或者是回调函数。

    Reactor模式:基于同步IO,事件分享者等待某个事件发生(文件描述符可读写或者socket可读写)。事件分享者就把这个事件传给事件注册的处理者或回到函数, 让后者来处理实际的读写操作

    Proactor模式:基于异步IO,事件处理者(或者事件分享器代为发起)直接发起一个异步读写操作(请求),而实际的工作是由操作系统来完成。事件处理者需要提供参数:用于存放读到数据的缓存区,读的数据大小,或者用于存放外发数据的缓存区,请求完后的回调函数等信息。事件分享器得知这个请求后,默默的在后面等待这个请求完成,然后转发完成事件给相应的事件处理者或者是回调函数。

    看看两种模式的区别:
Reactor的做法:
1,某个事件处理者宣称它对某个socket上的读事件很感兴趣。
2,事件分享者等着这个事件的 发生
3,当事件发生了,事件分享器被唤醒,负责通知事先那个事件的处理者。
4,事件处理者收到事件发生的消息后,就去socket上面读取数据了。
5,如果还需要读取这个socket上面的数据,它再次宣称对这个socket上的读事件感兴趣。
   一直重复上面的步骤。
Proactor的做法:
1,事件处理者直接发起一个读取操作的请求,这时事件处理者不会去关心这个读事件的完成情况。只是等着操作系统完成这个读事件后,回来告诉事件处理者就行了。
2,事件分享器等着这个读事件 完成
3,当事件分享器在等待这个事件完成的时候,其实操作系统已经在开始干活了,它从目标读取数据,放入到用户提供的缓冲区中,最后告诉事件分享器,读取事件完成了。
4,事件分享器告诉事件处理者,事件已经完成了。
5,事件处理者这时发现数据已经在自己提供的缓冲区里面了,这样就可以进去后续的业务处理了。
   如果可以,事件处理者还可以发起一个同样的请求,重复上面的步骤。

猜你喜欢

转载自jishuaige.iteye.com/blog/2355648