Netty4全方位解析

一、Netty4教程

Netty4是一款使用Java语言基于NIO框架构建的高性能异步网络通信框架,它提供了一种新的方式在Java平台上开发可扩展的、模块化的、高性能的、可维护的TCP/IP服务器和客户端。Netty4的特点是高性能、高清晰度,易于使用和灵活性。

在Netty4的教程中,我们可以学习如何使用Netty4来编写TCP/IP服务器、客户端和代码示例,如下所示:

public class NettyServer {
    public static void main(String[] args) throws Exception {
        //1.创建EventLoopGroup对象,是一个线程池,实际数量可以根据业务需求调整
        EventLoopGroup bossGroup = new NioEventLoopGroup(1); 
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            //2.创建ServerBootstrap对象,是启动服务的工具类
            ServerBootstrap b = new ServerBootstrap(); 
            b.group(bossGroup, workGroup)
             //3.设置TCP协议的Channel,NioServerSocketChannel是对java.nio.*包的封装
             .channel(NioServerSocketChannel.class) 
             //4.设置对client连接的数据处理逻辑PipeLine
             .childHandler(new ChannelInitializer<SocketChannel>() {     
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new NettyServerHandler());
                }
             })
             //5.设置TCP连接参数,SO_BACKLOG是指处于同一时刻待处理的连接队列的最大长度,超出的新连接会被拒绝,jvm会抛出ConnectionRefusedException
             .option(ChannelOption.SO_BACKLOG, 100)
             //6.设置缓冲区大小,通常可以不设置,会根据操作系统自适应,如果出现流量控制异常,可以考虑增加缓冲区大小
             .option(ChannelOption.SO_SNDBUF, 65535)
             .option(ChannelOption.SO_RCVBUF, 65535)
             //7.设置心跳检测机制以及关闭保护机制,保证TCP的正常关闭,防止TCP连接个数增长到JVM的最大值时出现宕机和内存耗尽等问题
             .childOption(ChannelOption.SO_KEEPALIVE, true)
             .childOption(ChannelOption.TCP_NODELAY, true);
            
            // Bind and start to accept incoming connections.
            //8.绑定端口
            ChannelFuture f = b.bind(PORT).sync(); 
            //9.监听channel关闭事件并执行shutdownGracefully关闭服务器和事件处理组
            f.channel().closeFuture().sync(); 
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }   
}

二、Netty4 Client Pool

在我们使用Netty4来编写客户端时,为了保证程序的高效性,需要使用连接池来减少重新建立连接带来的开销,使用连接池来管理大量的连接可以提高程序的并发量和性能。

下面是使用Apache Commons Pool结合Netty4实现连接池的代码示例:

public class NettyClientFactory extends BasePooledObjectFactory<NettyClient> {
    private String ip;
    private int port;

    public NettyClientFactory(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    @Override
    public NettyClient create() throws Exception {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(new NioEventLoopGroup());
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
        //设置重连机制
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel channel) throws Exception {
                channel.pipeline().addLast(new NettyClientHandler());
                channel.pipeline().addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS));
            }
        });
        ChannelFuture channelFuture = bootstrap.connect(ip, port);
        channelFuture.awaitUninterruptibly();
        if (channelFuture != null && channelFuture.isSuccess()) {
            return new NettyClient(channelFuture.channel());
        }
        return null;
    }

    @Override
    public PooledObject<NettyClient> wrap(NettyClient nettyClient) {
        return new DefaultPooledObject<>(nettyClient);
    }
}

三、Netty4源码

深入探究Netty4源码可以大幅度提高我们对Netty4的理解和认识,方便我们更好的使用和维护Netty4。

Netty4的主要源码结构如下:

+- common   -- 通用的代码
+- buffer   -- 字节缓存相关的代码,包括ByteBuf的实现、池化等
+- codec    -- 编码和解码相关的代码
+- channel  -- 整体框架代码,包括Channel和EventLoop的实现
+- handler  -- 处理器相关的代码
+- transport -- 传输相关的代码,包括网络传输和本地传输
+- resolver -- 解析器相关的代码
+- resolver-dns -- DNS解析器相关的代码

其中,参考使用ChannelInboundHandlerAdapter实现简单的数据读取处理,如下代码所示:

public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    private static final Logger log = LoggerFactory.getLogger(NettyServerHandler.class);

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        byte[] data = new byte[buf.readableBytes()];
        buf.readBytes(data);
        String request = new String(data, "UTF-8");
        log.info("Server received message: {}", request);

        ByteBuf resp = Unpooled.copiedBuffer("Hello, I'm server!", CharsetUtil.UTF_8);
        ctx.write(resp);
        ctx.flush();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("Exception caught: {}", cause.getMessage());
        ctx.close();
    }
}

四、Netty4 TCP开发

使用Netty的TCP开发,可以让我们非常轻松、高效、安全地实现TCP协议方面的开发工作。

下面是一个基于Netty4实现的TCP客户端代码示例:

public class NettyTcpClient {
    static final String HOST = System.getProperty("host", "127.0.0.1");
    static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));

    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup(1);
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new NettyClientHandler());
                 }
             });

            ChannelFuture f = b.connect(HOST, PORT).sync();

            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

五、Netty4核心原理

从底层分析Netty4的核心原理可以更好地帮助我们理解和使用Netty4。

Netty4的核心原理是基于NIO的异步网络通信,NIO通过Selector机制在一组Channel中逐个轮询事件,只有一个线程能够轮询并处理多个Channel,因此Netty4是通过NioEventLoop来负责I/O处理事件。

下面是NioEventLoop的源码片段:

public void run() {
    while (!Thread.interrupted()) {
        try {
            // 通过selector来取到Channel
            int numReady = selectStrategy.calculateStrategy(selectNowSupplier, hasTasks());
            // ...
            // 通过selector方式来获取I/O事件
            processSelectedKeys();
            // 处理Channel上的所有I/O任务和定时任务
            runAllTasks();
            // ...
        } catch (Throwable t) {
            // ...
        }
    }
    // ...
}

六、Netty4和5有什么区别

Netty5相比于Netty4在某些方面进行了较大的改变,比如在编解码器方面进行不同程度的优化、异步API使用更加灵活等。

下面是Netty4和Netty5对比的一些区别:

1、Netty4采用EventLoop和EventExecutor分离的设计思路,而Netty5采用异步的ActiveObject计算模型;
2、Netty5新增了一些基于HTTP/2协议的组件;
3、Netty5提供了更加灵活的异步API机制,可以更精细地控制异步事件的执行逻辑;
4、Netty5的通信协议栈进行了重新设计,比如在编解码器方面进行了不同程度的优化;
5、Netty5底层的异步事件处理引擎也进行了改进,更加适配不同场景的使用;

结语

Netty4是一个功能强大、易于使用、高性能的异步网络编程框架,它提供了丰富的网络协议支持和超高的吞吐量,是目前业界最为流行的异步网络编程框架之一。通过对Netty4的全方位解析,更加深入地理解Netty4的使用、原理和优势。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/241632.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 12:42
下一篇 2024-12-12 12:42

相关推荐

  • 金额选择性序列化

    本文将从多个方面对金额选择性序列化进行详细阐述,包括其定义、使用场景、实现方法等。 一、定义 金额选择性序列化指根据传入的金额值,选择是否进行序列化,以达到减少数据传输的目的。在实…

    编程 2025-04-29
  • java client.getacsresponse 编译报错解决方法

    java client.getacsresponse 编译报错是Java编程过程中常见的错误,常见的原因是代码的语法错误、类库依赖问题和编译环境的配置问题。下面将从多个方面进行分析…

    编程 2025-04-29
  • Python列表中负数的个数

    Python列表是一个有序的集合,可以存储多个不同类型的元素。而负数是指小于0的整数。在Python列表中,我们想要找到负数的个数,可以通过以下几个方面进行实现。 一、使用循环遍历…

    编程 2025-04-29
  • Python官网中文版:解决你的编程问题

    Python是一种高级编程语言,它可以用于Web开发、科学计算、人工智能等领域。Python官网中文版提供了全面的资源和教程,可以帮助你入门学习和进一步提高编程技能。 一、Pyth…

    编程 2025-04-29
  • at least one option must be selected

    问题解答:当我们需要用户在一系列选项中选择至少一项时,我们需要对用户进行限制,即“at least one option must be selected”(至少选择一项)。 一、…

    编程 2025-04-29
  • Java JsonPath 效率优化指南

    本篇文章将深入探讨Java JsonPath的效率问题,并提供一些优化方案。 一、JsonPath 简介 JsonPath是一个可用于从JSON数据中获取信息的库。它提供了一种DS…

    编程 2025-04-29
  • Python中引入上一级目录中函数

    Python中经常需要调用其他文件夹中的模块或函数,其中一个常见的操作是引入上一级目录中的函数。在此,我们将从多个角度详细解释如何在Python中引入上一级目录的函数。 一、加入环…

    编程 2025-04-29
  • 英语年龄用连字符号(Hyphenation for English Age)

    英语年龄通常使用连字符号表示,比如 “five-year-old boy”。本文将从多个方面探讨英语年龄的连字符使用问题。 一、英语年龄的表达方式 英语中表…

    编程 2025-04-29
  • Idea新建文件夹没有java class的解决方法

    如果你在Idea中新建了一个文件夹,却没有Java Class,应该如何解决呢?下面从多个方面来进行解答。 一、检查Idea设置 首先,我们应该检查Idea的设置是否正确。打开Id…

    编程 2025-04-29
  • Python周杰伦代码用法介绍

    本文将从多个方面对Python周杰伦代码进行详细的阐述。 一、代码介绍 from urllib.request import urlopen from bs4 import Bea…

    编程 2025-04-29

发表回复

登录后才能评论