【Java网络编程】Netty 网络框架

Netty是一个高性能、异步事件驱动的Java网络框架,提供对TCP、UDP和文件传输的支持。它解决了直接使用NIO的复杂性和陷阱,提供了更好的吞吐量和更低的延迟。Netty的主要优势包括自动处理粘包/分包、零拷贝实现、高效的Reactor线程模型以及丰富的组件如ByteBuf,减少了内存拷贝和GC频率。Netty通过CompositeByteBuf、wrap操作和FileRegion实现了零拷贝,提高了数据传输效率。此外,Netty的Channel、EventLoopGroup、ChannelPipeline和ChannelHandlerContext等组件协同工作,简化了网络编程流程。
摘要由CSDN通过智能技术生成

Netty 网络框架

Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。Netty 提供高性能和可扩展性,让你可以自由地专注于你真正感兴趣的东西,你的独特的应用!

Netty 是一个高性能、异步事件驱动网络库,它提供了对 TCP、UDP 和文件传输的支持使(这里首先就要搞清楚异步的 NIO 框架是什么意思)用更高效的 socket 底层,对 selector 空轮询引起的 cpu 占用飙升在内部进行了处理,避免了直接使用 NIO 的陷阱,简化了 NIO 的处理方式。采用多种decoder/encoder 支持,(后面我们会举例说明)对 TCP 粘包/分包进行自动化处理(后面也会演示说明)可使用接受/处理线程池,提高连接效率,对重连、心跳检测的简单支持可配置 IO 线程数、TCP 参数,TCP 接收和发送缓冲区使用直接内存代替堆内存,通过内存池的方式循环利用 ByteBuf 通过引用计数器及时申请释放不再引用的对象,降低了 GC 频率。高效的 Reactor 线程模型,大量使用了 volitale、使用了CAS 和原子类、线程安全类的使用、读写锁的使用。

在这里插入图片描述

Netty 技术和方法的特点

设计

  • 针对多种传输类型的统一接口 - 阻塞和非阻塞。
  • 简单但更强大的线程模型。
  • 真正的无连接的数据报套接字支持。
  • 链接逻辑支持复用。

易用性

  • 大量的 Javadoc 和 代码实例。
  • 除了在 JDK 1.6 + 额外的限制。(一些特征是只支持在 Java 1.7 +。可选的功能可能 有额外的限制。)

性能

  • 比核心 Java API 更好的吞吐量,较低的延时。
  • 资源消耗更少,这个得益于共享池和重用。
  • 减少内存拷贝。

健壮性

  • 消除由于慢,快,或重载连接产生的 OutOfMemoryError。
  • 消除经常发现在 NIO 在高速网络中的应用中的不公平的读/写。

安全

  • 完整的 SSL / TLS 和 StartTLS 的支持。
  • 运行在受限的环境例如 Applet 或 OSGI。

社区

  • 发布的更早和更频繁。
  • 社区驱动。

Netty 和 NIO 的关系

处理客户端连接的 EventLoopGroup 一般包含一个 NioEventLoop,NioEventLoop 即为一个 Selector(也是一个线程,负责 NIO),负责处理 NioServerSocketChannel 的状态监测,当有连接到来时,执行 accept(),新建一个 NioSocketChannel 负责与 Client 端的通信,NioSocketChannel 从 WorkerEventLoopGroup(NioEventLoop 数量根据配置生成)中选择一个 NioEventLoop register 进去,该 Channel 后续所有的 NIO 操作均由该 NioEventLoop 负责处理。

NioEventLoop 主要包含两部分操作:

  • processSelectedKeys() :即 selector 功能。
  • RunAllTasks():执行任务队列中的任务,主要是定时任务和外部工作线程添加的读写任务。

Netty 的优势

  • a、对 epoll 空轮询引起的 cpu 占用飙升在内部进行了处理,避免了直接使用 NIO 的陷阱。
  • b、简化了 NIO 的处理方式。
  • c、采用多种 decoder/encoder 支持。
  • d、对 TCP 粘包/分包进行自动化处理可使用接受/处理线程池。
  • e、提高连接效率,对重连、心跳检测的简单支持。
  • f、可配置 IO 线程数、TCP 参数,TCP 接收和发送缓冲区使用直接内存代替堆内存,通过内存池的方式循环利用 ByteBuf。
  • g、通过引用计数器及时申请释放不再引用的对象,降低了 GC 频率。
  • h、使用单线程串行化的方式,高效的 Reactor 线程模型。
  • i、大量使用了 volitale、使用了 CAS 和原子类、线程安全类的使用、读写锁的使用。

Netty 的编程流程及编码实践

服务端代码

public class EchoServer {
   
    public void run() throws Exception {
    // 进行服务器端的启动处理
        // 线程池是提升服务器性能的重要技术手段,利用定长的线程池可以保证核心线程的有效数量
        // 在 Netty 之中线程池的实现分为两类:主线程池(接收客户端连接)、工作线程池(处理客户端连接)
        EventLoopGroup bossGroup = new NioEventLoopGroup(10); // 创建接收线程池
        EventLoopGroup workerGroup = new NioEventLoopGroup(20); // 创建工作线程池
        System.out.println("服务器启动成功,监听端口为:" + HostInfo.PORT);
        try {
   
            // 创建一个服务器端的程序类进行 NIO 启动,同时可以设置 Channel
            ServerBootstrap serverBootstrap = new ServerBootstrap(); // 服务器端
            // 设置要使用的线程池以及当前的 Channel 类型
            serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class);
            // 接收到信息之后需要进行处理,于是定义子处理器
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
   
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
   
                    socketChannel.pipeline().addLast(new EchoServerHandler()); // 追加了处理器
                }
            });
            // 可以直接利用常亮进行 TCP 协议的相关配置
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 128);
            serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            // ChannelFuture 描述的时异步回调的处理操作
            ChannelFuture future = serverBootstrap.bind(HostInfo.PORT).sync();
            future.channel().closeFuture().sync();// 等待 Socket 被关闭
        } finally {
   
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
   
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
   
        // 当客户端连接成功之后会进行此方法的调用,明确可以给客户端发送一些信息
        byte data[] = "【服务器激活信息】连接通道已经创建,服务器开始进行响应交互。".getBytes();
        // NIO是基于缓存的操作,所以Netty也提供有一系列的缓存类(封装了NIO中的Buffer)
        ByteBuf buf = Unpooled.buffer(data.length); // Netty 自己定义的缓存类
        buf.writeBytes(data); // 将数据写入到缓存之中
        ctx.writeAndFlush(buf); // 强制性发送所有的数据
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   
        try {
   
            // 表示要进行数据信息的读取操作,对于读取操作完成后也可以直接回应
            // 对于客户端发送来的数据信息,由于没有进行指定的数据类型,所以都统一按照 Object 进行接收
            ByteBuf buf = (ByteBuf) msg; // 默认情况下的类型就是 ByteBuf 类型
            // 在进行数据类型转换的过程之中还可以进行编码指定(NIO 的封装)
            String inputData = buf.toString(CharsetUtil.UTF_8); // 将字节缓冲区的内容转为字符串
            String echoData = "【ECHO】" + inputData; // 数据的回应处理
            // exit 是客户端发送来的内容,可以理解为客户端的编码,而 quit 描述的是一个客户端的结束
            if ("exit".equalsIgnoreCase(inputData)) {
    // 进行沟通的端开
                echoData = "quit"; // 结束当前交互
            }
            byte[] data = echoData.getBytes()
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值