栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Reactor 和 Proactor 到底是什么玩意

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Reactor 和 Proactor 到底是什么玩意

网络编程中出了 IO 模型之外,另一个被经常提到的就是 Reactor 模型和 Proactor 模型, 其实这两个模型和 IO 模型有着重要的关系,看完本文你就知道了.

如果你对 IO 模型还不清楚,请先移步下面的文章后再回头来看本文.《到底什么是IO》https://mp.weixin.qq.com/s/OkIajg8aDlkLtsE81NP5jQ

在网络编程中,服务器设计的好坏直接影响到能支持的最大并发数,通常会考虑两种方式,一种是通过 线程的方式,另一种就是通过事件的方式. 

单线程

网络通信中, 客户端向服务器请求数据时,服务器通常有两种方式处理,一种就是单线程,这样做的话所有的客户端都需要排队等待, 如果服务端处理逻辑比较简单快速的话, 针对少量的客户端还是可以的,但是一旦客户端数量增加,服务端处理时间会线性增加, 如果处理逻辑复杂并且还涉及到 IO ,简直不可想象.

于是多线程模型出来了.

多线程

为了解决但线程带来的处理慢,延迟大的问题,引入了多线程. 服务器没收到一个客户端的连接就分配一个线程来处理, 当然分配的方式你可以选择 new 也可以选择线程池的方式,通常为了避免反复创建导致的资源浪费和性能低下问题而采用线程池的方式.

看似完美了,但是如果某些客户端连接在处理时比较耗时(由于各种原因,比如网络慢、数据量大处理复杂等),就会长期占用线程,导致其他客户端连接没办法获取线程处理.

事件模式

多线程的方式看似完美,但是有个问题就是, 线程利用率不高, 每来一个连接就分配一个线程,可能这个连接压根就没发数据,这岂不是白占着坑位吗?

基于事件模式就是连一个连接,服务端并不会立刻分配线程,而是监听事件(读、写、请求连接),有事件再分配线程进行处理.在实际工程中通常会将事件分发器(dispatcher)、处理器(handler)分开设计.

Reactor 

reactor “反应堆”, 对于所有来自客户端的事件作出反应,其实就是基于 NIO 的多路复用实现的一种方式.

根据 dispatcher、handler 线程模型可以分为 4种: 单 dispatcher 单 handler, 单 dispatcher 多 handler, 多 dispatcher 单 handler 以及多 dispatcher 多 handler, 但是 多 dispatcher 单 handler 对性能提升并没有太大价值,所以下面就讨论 3 种.

1. 单 dispatcher 单 handler

 

(1) 客户端连接过来, dispatcher 通过 select 轮询事件

(2) 如果是连接事件,交由 AcceptHandler 处理, 并向 select 注册 ready for reading(可读) 事件到 BusinessHandler

(3) 如果是 ready for reading 事件, 交由 BusinessHandler 处理,并返回结果

如果业务处理比较耗时的话,就会因为处理不过来而导致延迟.

2. 单 dispatcher 多 handler

 

工作过程类似,只是在收到 ready for reading 事件时, 交由一个单独的线程使用 BusinessHandler 处理.业务处理能力提高了,但是面对高并发时, 单线程的 dispatcher 成了瓶颈, 需要分发所有的事件.

3. 多 dispatcher 多 handler

也叫主从 Reactor 模式, 主线程中的 Dispatcher 只负责处理连接事件, 将成功的连接传给从 Reactor, 从 Reactor 处理调用业务处理器处理读写事件, 业务处理器又使用 worker 线程池进行业务处理.

 

 变种:

上图中 BusinessHandler 只负责读写调用,具体的业务处理在线程池中去做, 业务处理完后还得返回给 BusinessHandler 返回给客户端,涉及到数据共享问题,于是出现了变种:

所有的业务处理,包括 read 、业务处理、write 都在BusinessHandler 中的线程池中操作.

 

Netty 就是基于 reactor  的多 dispatcher 多handler 实现的.

Proactor

先看下 wiki 中的定义:

Proactor is a software design pattern for event handling in which long running activities are running in an asynchronous part. A completion handler is called after the asynchronous part has terminated. The proactor pattern can be considered to be an asynchronous variant of the synchronous reactor pattern.

Proactor 是一种用于事件处理的软件设计模式,其中长时间运行的活动(IO)在异步部分运行。异步部分终止后,将调用完成处理程序。前置器模式可以被认为是同步 reactor 模式的异步变体。

 

上面的图只是介绍了 proactor 的工作原理,实际编写代码时,可能非常简单, 比如 Java 中:

        AsynchronousServerSocketChannel  ssc = AsynchronousServerSocketChannel.open();

        // Bind the server socket to the local host and port
        InetAddress lh = InetAddress.getLocalHost();
        InetSocketAddress isa = new InetSocketAddress(lh, port);
        ssc.bind(isa);

        ssc.accept(this, new CompletionHandler() {
            @Override
            public void completed(AsynchronousSocketChannel result, AIOTimeServer attachment) {
                // 读取客户端数据
                ByteBuffer byteBuffer = ByteBuffer.allocate(2000);
                result.read(byteBuffer);
  

                String responsedocument = ("" +
                        "AIO Server: " +  System.currentTimeMillis() + "");

                String responseHeader = ("HTTP/1.1 200 OKrn" +
                        "Content-Type: text/html; charset=UTF-8rn" +
                        "Content-Length: " + responsedocument.length() +
                        "rnrn");

                try {
                    // 响应客户端数据
                    result.write(encoder.encode(CharBuffer.wrap(responseHeader)));
                    result.write(encoder.encode(CharBuffer.wrap(responsedocument)));
                } catch (IOException e) {
                    e.printStackTrace();
                }


                try {
                    // 关闭连接
                    result.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }

            @Override
            public void failed(Throwable exc, AIOTimeServer attachment) {
                System.out.println("failed");
            }
        });
    

 

所以 Proactor 也是基于事件处理的软件设计模式, 对 OS 的数据ready 事件作出反应, 所以依赖于操作系统的 AIO , windows 对 AIO 支持较好, POSIX 中已经定义了接口 aio_read/aio_write , 但是Linux 中一直没有实现, 直到 2.6 才真正实现可能还不完美.


如果觉得还不错的话,关注、分享、在看, 原创不易,且看且珍惜~

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/752474.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号