Netty Reactor 模式

225 阅读1分钟

单线程 Reactor 模式

示例代码

  • EchoServerReactor.java 回显服务器
    package com.netty.im.Reactor.singleThread;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    import java.util.Set;
    
    /**
     * Created by andy on 2020/8/21.
     */
    public class EchoServerReactor implements Runnable{
      Selector selector;  // 每个线程配置唯一一个 selector 选择器
      ServerSocketChannel serverSocket; // 服务端监听 channel
      Logger logger = LoggerFactory.getLogger(EchoServerReactor.class);
      
      EchoServerReactor() throws IOException{
          serverSocket = ServerSocketChannel.open();
          selector = Selector.open(); 
          serverSocket.configureBlocking(false); 
          serverSocket.bind(new InetSocketAddress("127.0.0.1", 8080)); // 绑定监听 ip 与 port
          SelectionKey sk = serverSocket.register(selector, SelectionKey.OP_ACCEPT); // 将监听通道注册到 selector 选择器上
          sk.attach(new AcceptorHandler()); // selectionKey 绑定接受请求 handler处理器
      }
    
      @Override
      public void run() {
          try {
              while (!Thread.interrupted()) {
                  selector.select(); // 阻塞,直到有通道准备就绪 or 该 selector 的 wakeup 方法被 invoke or the current thread is interrupted
                  Set<SelectionKey> selected = selector.selectedKeys(); // 获取通道准备就绪的 selectionKey
                  Iterator<SelectionKey> it = selected.iterator();
                  while (it.hasNext()) {
                      SelectionKey sk = it.next();
                      dispatch(sk);
                  }
                  selected.clear();
              }
          }catch (IOException ex) {
              ex.printStackTrace();
          }
      }
    
      private void dispatch(SelectionKey sk) {
          Runnable handler = (Runnable) sk.attachment(); // 获取绑定在 selectionKey 选择键上的 handler 处理器
          if(handler != null) {
              handler.run();
          }
      }
      
      class AcceptorHandler implements Runnable {
          @Override
          public void run() {
              try {
                  SocketChannel socketChannel = serverSocket.accept();
                  if(socketChannel !=null) {
                      new EchoHandler(selector, socketChannel);
                  }
              }catch (IOException ex) {
                  ex.printStackTrace();
              }
          }
      }
    
      public static void main(String[] args) throws IOException{
          new Thread(new EchoServerReactor()).start();
      }
    }
    

多线程 Reactor 模式

示例代码

  • MultiThreadEchoServeReactor.java 回显服务器
    package com.netty.im.Reactor.mutilThread;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.concurrent.atomic.AtomicInteger;
    /**
     * Created by andy on 2020/8/21.
     */
    public class MultiThreadEchoServeReactor {
      ServerSocketChannel serverSocket;
      AtomicInteger next = new AtomicInteger(0);
      Selector[] selectors = new Selector[2];
      SubReactor[] subReactors;
    
      MultiThreadEchoServeReactor() throws IOException {
          selectors[0] = Selector.open();
          selectors[1] = Selector.open();
          InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8080);
          serverSocket.socket().bind(address);
          serverSocket.configureBlocking(false);
          SelectionKey sk = serverSocket.register(selectors[0], SelectionKey.OP_ACCEPT);
          sk.attach(new AcceptHandler());
    
          SubReactor subReactor1 = new SubReactor(selectors[0]);
          SubReactor subReactor2 = new SubReactor(selectors[1]);
          subReactors = new SubReactor[]{subReactor1, subReactor2};
      }
    
      private void startService() {
          new Thread(subReactors[0]).start();
          new Thread(subReactors[1]).start();
      }
    
      private void dispatch(SelectionKey sk) {
          Runnable handle = (Runnable) sk.attachment();
          if(null != handle) {
              handle.run();
          }
      }
    
      class AcceptHandler implements Runnable {
          @Override
          public void run() {
              try {
                  SocketChannel channel = serverSocket.accept();
                  if(channel != null) {
                      // 绑定 handler
                      new MultiThreadEchoHandler(selectors[next.get()], channel);
                  }
              }catch (IOException ex) {
                  ex.printStackTrace();
              }
              if(next.incrementAndGet() == selectors.length) {
                  next.set(0);
              }
          }
      }
      
      class SubReactor implements Runnable {
    
          private Selector selector;
          SubReactor(Selector selector) {
              this.selector = selector;
          }
          @Override
          public void run() {
              try {
                  while (!Thread.interrupted()) {
                      selector.select();
                      Set<SelectionKey> selectedKeys = selector.selectedKeys();
                      Iterator<SelectionKey> it = selectedKeys.iterator();
                      while (it.hasNext()) {
                          SelectionKey sk = it .next();
                          dispatch(sk);
                      }                }
              }catch (IOException ex) {
                  ex.printStackTrace();
              }
          }
      }
    }