当前位置: 首页 > article >正文

[Netty源码] 各个组件介绍 (一)

文章目录

      • 1.Netty简单的demo
      • 2.NIO的定式Api
      • 3.组件介绍
        • 3.1 EventLoop
        • 3.2 Channel
        • 3.3 ChannelHandler
        • 3.4 ChannnelHandlerContext
        • 3.5 ChannelPipeline
        • 3.6 Bootstrap
        • 3.7 ByteBuf

1.Netty简单的demo

Netty高并发高性能:

  • 主从Reactor线程模型
  • NIO多路复用非阻塞
  • 无锁串行化设计思想
  • 支持高性能序列化协议
  • 零拷贝(直接内存的使用)
  • ByteBuf内存池设计
  • 灵活的TCP参数配置能力
  • 并发优化
public class Server {
    public static void main(String[] args) throws Exception{
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap()
                    .group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue")
                    // 对应 .accept, 新连接介入
                    .handler(new ServerHandler())
                    .childHandler(new ChannelInitializer<ServerSocketChannel>() {
                        @Override
                        protected void initChannel(ServerSocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new AuthHandler());                        
                        }
                    });
            ChannelFuture f = b.bind(8080).sync();
            f.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}

Netty线程模型图

在这里插入图片描述

2.NIO的定式Api

Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
InetSocketAddress address = new InetSocketAddress(1233);
ssc.configureBlocking(false);
ssc.bind(address);
ssc.register(selector, SelectionKey.OP_ACCEPT);
for (;;) {
    int select = selector.select();
    if (select > 0) {
        Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
        while (iterator.hasNext()) {
            SelectionKey selectionKey = iterator.next();
            iterator.remove();
            if (selectionKey.isAcceptable()) {
                SocketChannel channel = ssc.accept();
                channel.configureBlocking(false);
                channel.register(selector,SelectionKey.OP_READ);
            }
            if (selectionKey.isReadable()) {
                ByteBuffer buffer = ByteBuffer.allocate(10);
                SocketChannel channel = (SocketChannel)selectionKey.channel();
                // 读取channel数据。。
                channel.close();
            }
        }
    }
}

nio的几个重要组件:

  1. Selector(事件选择器)
  2. Channel(通信通道)
  3. Buffer(通信载体)

3.组件介绍

netty就是基于nio做的一次优秀的封装

netty的几个重要组件:

  1. NioEventLoop(线程组件), 对应一个Thread

  2. Channel(通信通道,netty做了一层封装), 对应一个Socket连接

  3. ChannelPipeline(消息通知链), 对应一个逻辑处理链 Logic Chain

  4. ChannelHandler(真正触发事件干活的), 对应具体的逻辑 Logic

  5. ChannelHandlerContext(对handler做了一层包装), 对逻辑的封装

  6. ByteBuf: 数据流的读写基于ByteBuf操作的

  7. Bootstrap: 可以让ChannalPipline、ChannelHandler和EventLoop一起有效组合成一个可以实际运行的应用程序

3.1 EventLoop

做的大部分和线程处理相关的事情, 无论是服务器线程还是客户端线程

NioEventLoop存在boss与work之分, boss代表一个总线程, work代表很多工作线程, 简而言之就是一个boss管理多个work。

在这里插入图片描述

EventLoopGroup和EventLoop和channel的关系:

在这里插入图片描述

EventLoopGroup的责任是将新的连接(也就是新的Channel)分配给EventLoopGroup内关联的EventLoop

NioEventLoop源码中表面了Reactor网络模型。

3.2 Channel

Channel对应的是Socket连接, 相当于一个Channel就是一个socket连接。

客户端创建一个连接或者服务端收到连接请求都会创建一个Channel,所有的I/O事件都由Channel产生,这些事件包含read、write、connet、accept、close。Channel为用户提供了:

  • 当前网络连接通道的状态
  • 网络连接的配置信息
  • 异步的网络I/O操作,操作返回ChannelFuture实例,通过ChannelFuture可以操作异步的状态,例如取消、关闭等

不同的协议与不同的阻塞类型的连接都有与之对应的Channel类型,下面是常用的Channel类型:

  • NioSocketChannel 异步的客户端 TCP Socket 连接。
  • NioServiceSocketChannel 异步的服务器端 TCP Socket 连接。
  • NioDatagramChannel 异步的 UDP 连接。
  • NioSctpChannel 异步的客户端 Sctp 连接。
  • NioSctpServiceChannel 异步的 Sctp 服务器端连接
  • EpollSocketChannel 异步的客户端TCP Socket连接,底层使用epoll
  • EpollServiceSocketChannel异步的服务器端 TCP Socket 连接,底层使用epoll

3.3 ChannelHandler

ChannelHandler是一个处理Channel事件的接口, 通过ChannelHandler可以处理任一的网络I/O事件与数据, 引导过程会使用ChannelPipeline将多个ChannelHandler串起来。

通常会通过继承ChannelInboundHandler与ChannelOutboundHandler两个子接口类型来处理业务逻辑, 这些业务逻辑包含数据的编码、解码、读取、写入以及事件传递等待事情。

3.4 ChannnelHandlerContext

将对应的ChannelHandler托管, 在ChannelPipeline中起到事件向下传递与调用ChannelHandler的作用,另外还存储着当前Channel的相关上下文信息等。

3.5 ChannelPipeline

它让Netty在处理各种各样的业务情况时有了很强扩展性与适应性, 使得业务可以在运行时对整个ChannelPipeline中的过滤器(这里的过滤器实现类型都是ChannelHandler)进行调整以支持不同的业务形态。

在这里插入图片描述

ChannelPipeline中使用一张链表存储着所有ChannelHandler, 会区分入站ChannelInboundHanndler和出站ChannelOutboundHanndler的类型。

3.6 Bootstrap

Bootstrap是一个应用程序中启动过程中的配置,通过这些配置让应用程序能正常的运行起来的一个过程。
这个概念有点像操作系统的启动过相近,操作系统的启动过程同样有一个引导的过程。

在这里插入图片描述

Bootstrap为客户端是引导, ServerBootstap为服务端的引导

3.7 ByteBuf

在这里插入图片描述

这里一个创建方式是直接内存一个是堆内存

ByteBuf buf1 = ByteBufAllocator.DEFAULT.buffer();
ByteBuf buf2 = ByteBufAllocator.DEFAULT.directBuffer();
ByteBuf buf3 = ByteBufAllocator.DEFAULT.heapBuffer();

直接内存对GC压力小,因为这部分内存不受JVM垃圾回收的管理,但也要注意及时主动释放

并且Netty的ByteBuf支持池化, 可以重用池中 ByteBuf实例, 内存分配算法提高分配效率, 并发时候可以减少内存溢出, 使得节约内存


http://www.kler.cn/a/2717.html

相关文章:

  • libvirt零知识学习6 —— libvirt源码编译安装(4)
  • js调用gpt3.5
  • ViewService——一种保证客户端与服务端同步的方法
  • 超级实用,解密云原生监控技术,使用prometheus轻松搞定redis监控
  • 【JavaEE】 多线程的风险-线程安全
  • 《程序员成长历程的四个阶段》
  • 关于中级开发工程师常问的面试题
  • CSDN 第三十九期竞赛题解
  • 如何做好数字化知识管理?
  • Linux内核IO基础知识与概念
  • python中pandas模块数据处理小案例
  • Linux内核六大进程通信机制原理
  • 自己动手做chatGPT:向量的概念和相关操作
  • 7个最受瞩目的 Python 库,提升你的开发效率
  • 【Mysql系列】——详细剖析数据库“索引”【上篇】
  • 【排序算法】
  • Tomcat And Servlet (1)
  • 构造函数为什么不能为虚函数?析构函数为什么要为虚函数?
  • Linux内核进程管理几种CPU调度策略
  • 全网最完整,接口测试总结彻底打通接口自动化大门,看这篇就够了......