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/zh-tw/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

發表回復

登錄後才能評論