webFlux&Reactor

2021-04-03 02:25

阅读:662

  外部条件有限制,所以 Buffer 需要有上限;

  Buffer 达到上限这个现象,有一个简化的等价词叫做 Backpressure;

  Backpressure 的出现其实是一种危险边界,唯一的选择是丢弃新事件。

Reactor:

  Reactor模式也叫反应器模式,大多数IO组件如reids,netty都在使用的IO模式,以此来解决高性能并发。Reactor被分为handlerreactor两个部分,前者负责业务处理,后者负责io接受分发。

  回顾一下IO历史:

    连轴转:一个while处理全部请求(单线程)。一个请求阻塞全部阻塞。

    connection per thread:一个请求一个线程。一个线程只能处理一个请求,即使语法上允许一个线程处理多个请求,但是一个线程上的一个请求被阻塞,其他也会阻塞;每个线程都是系统的资源,耗费资源巨大,创建销毁线程也需要消耗资源。

    Java.NIO: (NIO的Selector网络通讯就是一个单线程版的Reactor)。一个典型的NIO代码:

 1 static class Server
 2     {
 3 
 4         public static void testServer() throws IOException
 5         {
 6 
 7             // 1、获取Selector选择器
 8             Selector selector = Selector.open();
 9 
10             // 2、获取通道
11             ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
12             // 3.设置为非阻塞
13             serverSocketChannel.configureBlocking(false);
14             // 4、绑定连接
15             serverSocketChannel.bind(new InetSocketAddress(SystemConfig.SOCKET_SERVER_PORT));
16 
17             // 5、将通道注册到选择器上,并注册的操作为:“接收”操作
18             serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
19 
20             // 6、采用轮询的方式,查询获取“准备就绪”的注册过的操作
21             while (selector.select() > 0)
22             {
23                 // 7、获取当前选择器中所有注册的选择键(“已经准备就绪的操作”)
24                 Iterator selectedKeys = selector.selectedKeys().iterator();
25                 while (selectedKeys.hasNext())
26                 {
27                     // 8、获取“准备就绪”的时间
28                     SelectionKey selectedKey = selectedKeys.next();
29 
30                     // 9、判断key是具体的什么事件
31                     if (selectedKey.isAcceptable())
32                     {
33                         // 10、若接受的事件是“接收就绪” 操作,就获取客户端连接
34                         SocketChannel socketChannel = serverSocketChannel.accept();
35                         // 11、切换为非阻塞模式
36                         socketChannel.configureBlocking(false);
37                         // 12、将该通道注册到selector选择器上
38                         socketChannel.register(selector, SelectionKey.OP_READ);
39                     }
40                     else if (selectedKey.isReadable())
41                     {
42                         // 13、获取该选择器上的“读就绪”状态的通道
43                         SocketChannel socketChannel = (SocketChannel) selectedKey.channel();
44 
45                         // 14、读取数据
46                         ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
47                         int length = 0;
48                         while ((length = socketChannel.read(byteBuffer)) != -1)
49                         {
50                             byteBuffer.flip();
51                             System.out.println(new String(byteBuffer.array(), 0, length));
52                             byteBuffer.clear();
53                         }
54                         socketChannel.close();
55                     }
56 
57                     // 15、移除选择键
58                     selectedKeys.remove();
59                 }
60             }
61 
62             // 7、关闭连接
63             serverSocketChannel.close();
64         }
65 
66         public static void main(String[] args) throws IOException
67         {
68             testServer();
69         }
70     }

从上面代码可知,NIO通过一个线程就完成了传统IO需要大量资源提供的IO操作,且效率极高。但是缺点也很明显,任何IO资源的操作都有可能导致阻塞,进而导致这个NIO系统阻塞。这在web项目中是不能容忍的。所以也就没有单线程的Reactor。

  多线程的Reactor:

    1. Handler资源处理器的执行被放入线程池中进行,以多线程的方式进行资源处理。(主要)

    2. 而对于Reactor而言,可以仍为单个线程。如果服务器为多核的CPU,为充分利用系统资源,可以将Reactor拆分为两个线程。(升级)

Reactor模式的优点:

1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;

2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;

3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;

4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性; 


评论


亲,登录后才可以留言!