• Netty架构设计


    目录

    Selector模型

    SelectableChannel

    Channel注册到Selector

    SelectionKey

    遍历SelectionKey

    事件驱动

    责任链模式


    Selector模型

    Java NIO是基于Selector模型来实现非阻塞IO,Netty底层基于Java NIO实现的,因此也使用了Selector模型。

     Selector提供了选择执行已经就绪的任务的能力。从底层看,Selector会轮询Channel是否已经准备好执行每个IO操作。Selector允许单个线程处理多个Channel。

    SelectableChannel

            并不是所有的Channel都是可以被Selector复用的,只有抽象类SelectableChannel的子类才能被Selector复用。FileChannel就不能被复用,因其不是SelectableChannel的子类。

            SelectableChannel并发安全。

    Channel注册到Selector

    1. /*
    2. *Registers this channel with the given selector, returning a selection
    3. * key.
    4. *@param sel
    5. * The selector with which this channel is to be registered
    6. *
    7. * @param ops
    8. * The interest set for the resulting key
    9. *
    10. * @param att
    11. * The attachment for the resulting key; may be null
    12. **/
    13. public final SelectionKey register(Selector sel, int ops)
    14. public abstract SelectionKey register(Selector sel, int ops, Object att)

    可供Selector查询的通道操作主要有四种:

    1. public static final int OP_READ = 1 << 0;
    2. public static final int OP_WRITE = 1 << 2;
    3. public static final int OP_CONNECT = 1 << 3;
    4. public static final int OP_ACCEPT = 1 << 4;
    • 某个SocketChannel通道可以连接到一个服务器,则处于OP_CONNECT状态
    • 一个ServerSocketChannel服务器通道准备好接收新接入的连接,则处于OP_ACCEPT状态
    • 一个有数据可读的Channel,OP_READ状态
    • 一个等待写数据的通道,OP_WRITE状态

    SelectionKey

    Channel和Selector关系确定好之后,一旦Channel处于某种就绪状态,就可以被选择器查询到,使用Selector.select()方法。

    获取感兴趣的事件集合:

    public abstract int interestOps();

    获取通道已经准备就绪的操作的集合:

    public abstract int readyOps();

    从SelectionKey访问Channel和Selector:

    1. selectionKey.channel();
    2. selectionKey.selector();

    可以将一个对象或其他信息附着到SelectionKey上:

    1. selectionKey.attach(theObject);
    2. selectionKey.attachment();
    3. channel.register(selector, SelectionKey.OP_READ, theObject)

    遍历SelectionKey

    1. Selector selector = Selector.open();
    2. ByteBuffer buffer = ByteBuffer.allocate(16);
    3. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    4. serverSocketChannel.configureBlocking(false);
    5. serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    6. serverSocketChannel.bind(new InetSocketAddress(8080));
    7. while (true) {
    8. selector.select();
    9. Iterator iterator = selector.selectedKeys().iterator();
    10. while (iterator.hasNext()) {
    11. SelectionKey selectionKey = iterator.next();
    12. if(selectionKey.isAcceptable()) {
    13. ServerSocketChannel channel = (ServerSocketChannel) selectionKey.channel();
    14. SocketChannel socketChannel = channel.accept();
    15. socketChannel.configureBlocking(false);
    16. socketChannel.register(selector, SelectionKey.OP_READ);
    17. }
    18. if(selectionKey.isReadable()) {
    19. SocketChannel channel = (SocketChannel) selectionKey.channel();
    20. channel.read(buffer);
    21. buffer.flip();
    22. ByteBufferUtil.debugAll(buffer);
    23. buffer.clear();
    24. }
    25. iterator.remove();
    26. }
    27. }

    每次迭代记得调用iterator.remove。

    事件驱动

    Netty是异步的事件驱动网络应用框架。

    责任链模式

  • 相关阅读:
    Jenkins 配置邮件
    RAG开山之作:结合参数化与非参数化记忆的知识密集型NLP任务新解法
    [Codeforces] number theory (R1200) Part.9
    GPS北斗时钟服务器(NTP网络时钟系统)施工部署方案
    3D建模基础教程:编辑样条线【子层级】
    Debian直接安装mysql8
    2022-2023罗戈物流行业年度报告,物流人必看报告!
    kubernetes集群编排(6)
    Gossip协议是什么
    人工智能之地形导航系统
  • 原文地址:https://blog.csdn.net/lovelovelovelovelo/article/details/127717242