Netty:java高性能網絡編程的基石(下)

一、Netty是什么?為什么需要它?

Netty是一個異步事件驅動的網絡應用框架,基于Java NIO技術封裝,用于快速開發高性能、高可靠性的網絡服務器和客戶端程序。作為當前最流行的NIO框架之一,支撐著Dubbo、RocketMQ、Elasticsearch等眾多分布式系統的底層通信。

為什么需要Netty?

傳統BIO的困境: 阻塞式IO模型(BIO)中每個連接都需要獨立線程,海量連接時線程資源耗盡。
NIO的復雜性: 雖然Java原生NIO解決了BIO的阻塞問題,但其Selector、Buffer、Channel等API復雜難用,開發維護成本高。

  • Netty的優勢:
    優雅的API設計: 屏蔽NIO底層細節,提供易用的編程模型。
    高性能架構: 基于主從Reactor線程模型,支持百萬級并發連接。
    豐富的協議支持: 內置HTTP、WebSocket等協議編解碼器,開箱即用。
    健壯性保障: 完善的異常處理機制,避免網絡波動導致服務崩潰。
// 傳統BIO線程模型
ServerSocket serverSocket = new ServerSocket(8080);
while(true) {Socket socket = serverSocket.accept(); // 阻塞等待連接new Thread(() -> handleRequest(socket)).start(); // 每個連接一個線程
}

二、Netty如何解決粘包/拆包?

粘包/拆包問題根源: TCP是流式協議,像水管里的水,無法區分消息邊界。發送方多次寫入的數據可能被接收方一次讀取(粘包),或一個完整數據包被分多次讀取(拆包)。

Netty的解決方案:

1. 固定長度解碼器 (FixedLengthFrameDecoder)

每個數據包固定長度,不足則補位。

// 服務端添加解碼器
ch.pipeline().addLast(new FixedLengthFrameDecoder(10)); // 每個數據包10字節
ch.pipeline().addLast(new StringDecoder()); 
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {System.out.println("收到消息: " + msg);}
});
2. 分隔符解碼器 (DelimiterBasedFrameDecoder)

使用特殊符號(如換行符)作為消息結束標志。

// 使用"$_"作為分隔符
ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
ch.pipeline().addLast(new StringDecoder());
3. 長度字段解碼器 (LengthFieldBasedFrameDecoder)

協議頭中定義長度字段,指明數據包長度。

// 協議格式:長度字段(4字節) + 數據內容
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4)); // 最大長度1024,長度字段偏移0,長度4字節
ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));

三、私有協議設計與實現

實現步驟:

1. 定義協議格式

以簡單的協議為例:

字段魔數(4字節)版本(1字節)數據長度(4字節)數據內容
示例0xCAFEBABE1lendata
2. 自定義編碼器

繼承MessageToByteEncoder,將消息對象轉為字節流。

public class CustomEncoder extends MessageToByteEncoder<CustomMessage> {@Overrideprotected void encode(ChannelHandlerContext ctx, CustomMessage msg, ByteBuf out) {out.writeInt(0xCAFEBABE); // 魔數out.writeByte(1); // 版本out.writeInt(msg.getData().length); // 數據長度out.writeBytes(msg.getData()); // 數據內容}
}
3. 自定義解碼器

繼承ReplayingDecoder,解析字節流為消息對象。

public class CustomDecoder extends ReplayingDecoder<Void> {@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {int magic = in.readInt(); // 讀取魔數if(magic != 0xCAFEBABE) {throw new IllegalStateException("協議錯誤");}byte version = in.readByte(); // 版本校驗int length = in.readInt(); // 數據長度byte[] data = new byte[length];in.readBytes(data); // 讀取數據out.add(new CustomMessage(version, data));}
}

處理半包問題:ReplayingDecoder內部通過檢查可讀字節數自動處理數據不完整的情況,當可讀字節不足時等待下次數據到達。

四、總結

Netty通過精妙的架構設計和豐富的組件庫,極大簡化了網絡編程的復雜性。掌握粘包/拆包解決方案和自定義協議開發能力,是構建高性能通信系統的關鍵。建議讀者結合官方文檔和實際項目案例,深入理解Netty的線程模型、內存管理等高級特性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/73744.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/73744.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/73744.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode-47.全排列II

如何在有重復值的時候節省時間是優化重點。 基礎寫法肯定是按無重復值時的全排列寫&#xff0c;在其中要加上防止走重復路徑的分支。 能防止的也只有同層&#xff0c;如果同層走一個值&#xff0c;但是該值重復&#xff0c;且走過了&#xff0c;則放棄走該分支。所以設layer_u…

函數(函數的概念、庫函數、自定義函數、形參和實參、return語句、數組做函數參數、嵌套調用和鏈式訪問、函數的聲明和定義、static和extern)

一、函數的概念 ?C語?中的函數&#xff1a;?個完成某項特定的任務的??段代碼 ?函數又被翻譯為子函數&#xff08;更準確&#xff09; ?在C語?中我們?般會?到兩類函數&#xff1a;庫函數 ?定義函數 二、庫函數 1 .標準庫和頭文件 ?C語?的國際標準ANSIC規定了?…

孜然SEO靜態頁面生成系統V1.0

孜然SEO靜態頁面生成系統&#xff0c;1秒生成上萬個不同的靜態單頁系統&#xff0c;支持URL裂變采集&#xff0c;采集的內容不會重復&#xff0c;因為程序系統自帶AI重寫算法&#xff0c;AI擴寫算法&#xff0c;可視化的蜘蛛池系統讓您更清楚的獲取到信息&#xff01; 可插入二…

Secs/Gem第一講 · 總結精華版(基于secs4net項目的ChatGpt介紹)

好的&#xff01;這就是《第一講 總結精華版》——為背誦準備的口述速成稿&#xff0c;適合面試前復習答題用。我們會分為兩個部分&#xff1a; 第一部分&#xff1a;一整段口述稿&#xff0c;可以當成面試時開口自我介紹用&#xff1b;第二部分&#xff1a;要點清單關鍵詞串…

預處理指令中#if 和 #endif的用法

在 C 語言中&#xff0c;#if 和 #endif 是預處理指令&#xff0c;用于條件編譯。它們的核心作用是&#xff1a;根據預處理器能夠識別的條件&#xff08;通常是宏定義或常量表達式&#xff09;&#xff0c;決定某段代碼是否參與編譯。 — 基本功能 #if 用于開啟一個條件編譯塊…

【數據庫】掌握MySQL事務與鎖機制-數據一致性的關鍵

在數據庫的世界里&#xff0c;數據就是一切。而確保數據的準確性和一致性&#xff0c;則是數據庫系統的核心任務之一。想象一下&#xff0c;如果沒有合適的機制&#xff0c;當多個用戶同時試圖修改同一條數據時&#xff0c;會發生什么&#xff1f; chaos&#xff08;混亂&#…

linux 基礎網絡配置文件

使用“ifconfig”命令查看網絡接口地址 直接執行“iconfg”命令后可以看到ens33、10、virbr0這3個網絡接口的信息&#xff0c;具體命令如下 ifconfig ##查看網絡接口地址 ens33:第一塊以太網卡的名稱 lo:“回環”網絡接口 virbr0:虛擬網橋的連接接口 查看指…

OpenCV特征提取與深度學習CNN特征提取差異

一、特征生成方式 ?OpenCV傳統方法? ?手工設計特征?&#xff1a;依賴人工設計的算法&#xff08;如SIFT、FAST、BRIEF&#xff09;提取圖像中的角點、邊緣等低層次特征&#xff0c;需手動調整參數以適應不同場景?。?數學驅動?&#xff1a;基于梯度變化、幾何變換等數學規…

五種方案實現雙鏈路可靠數據傳輸

本文介紹五種雙鏈路數據傳輸方案,目標是利用設備的多個傳輸通道,(如雙有線網口,網口+wifi, 網口+5G等場景 , 網口+ 自組網, 自組網 + 5G等),將數據復制后分流、分路同時傳輸,以期提高數據傳輸可靠性,滿足高可靠性傳輸的應用場景需求。部分方案給出了實際驗證結果 。 …

【備賽】遇到的小問題-1

問題描述-1 想實現的功能是&#xff0c;通過ADC實時測量某引腳的電壓及其占空比。 可以通過旋轉電位器&#xff0c;更改其電壓。 首先我定義了這幾個變量 uint32_t adc_value;//HAL庫函數里面得出的采樣值(實時更新) uint32_t percentage6;//占空比&#xff0c;隨著adc_val…

最大公約數

4.最大公約數 - 藍橋云課 最大公約數 題目描述 給定兩個正整數 A,B&#xff0c;求它們的最大公約數。 輸入描述 第1行為一個整數 T&#xff0c;表示測試數據數量。 接下來的 T 行每行包含兩個正整數 A,B。 1≤T≤105&#xff0c;1≤A,B≤109。 輸出描述 輸出共 T 行&…

TMHMM2.0-蛋白跨膜螺旋預測工具-centos-安裝+配置+排錯

參考&#xff1a; A. Krogh, B. Larsson, G. von Heijne, and E. L. L. Sonnhammer. Predicting transmembrane protein topology with a hidden Markov model: Application to complete genomes. Journal of Molecular Biology, 305(3):567-580, January 2001. centos&#x…

docker run 命令常用參數

docker run 命令 用于從鏡像創建并啟動一個新的容器。 基本語法&#xff1a; docker run [OPTIONS] IMAGE [COMMAND] [ARG...]常用選項分類說明 容器配置 --name 為容器指定名稱&#xff08;默認隨機生成&#xff09;。 示例&#xff1a; docker run --name my_container …

Zbrush插件安裝

安裝目錄在: ...\Zbrush2022\ZStartup\ZPlugs64

pandas中excel自定義單元格顏色

writerpd.ExcelWriter(filepathf05教師固定學生占比1月{today}.xlsx,engineopenpyxl) df.to_excel(writer,sheet_name明細) piv1.to_excel(writer,sheet_name1月分布) wswriter.book.create_sheet(口徑) ws.cell(1,1).value綜合占比&#xff1a; ws.cell(1,2).value固定學生占比…

整體二分算法講解及例題

算法思想 整體二分&#xff0c;帶有二分二字那么就一定和二分脫不了干系。 整體二分算法常用來解決詢問區間的第 k k k小值的問題&#xff0c;思路如下&#xff1a; 我們二分的對象是這道題目給定的值域&#xff0c;及最小值與最大值之間的區間&#xff0c;在題目給定的數組中…

python+flask實現360全景圖和stl等多種格式模型瀏覽

1. 安裝依賴 pip install flask 2. 創建Flask應用 創建一個基本的Flask應用&#xff0c;并設置路由來處理不同的文件類型。 from flask import Flask, render_template, send_from_directory app Flask(__name__) # 設置靜態文件路徑 app.static_folder static app.r…

XML轉義符詳解:如何在XML中正確處理特殊字符

在XML中&#xff0c;某些字符具有特殊含義&#xff0c;如果直接在文本中使用這些字符&#xff0c;可能會導致XML解析錯誤。為了避免這些問題&#xff0c;我們需要使用XML轉義符或CDATA段來處理這些特殊字符。本文將詳細介紹XML轉義符的使用方法、注意事項&#xff0c;并結合實際…

IPC 進程間通信(一):管道(匿名管道進程池)

1. 初識進程間通信 1.1進程間通信的目的&#xff1a; 1、數據傳輸&#xff1a;一個進程需要將它的數據發送給另一個進程 2、資源共享&#xff1a;多個進程之間共享同樣的資源 3、通知事件&#xff1a;一個進程需要向另一個或一組進程發送消息&#xff0c;通知它&#xff08;它…

Linux-數據結構-單鏈表練習-雙鏈表

一.單鏈表練習和一些功能實現 【1】單鏈表實現字典查詢 &#xff08;1&#xff09;定義存放數據的結構體&#xff0c;在每次向里面存放數據時候需要清空 &#xff08;2&#xff09;對字典進行切割 空格切割字母&#xff0c;再從剩余里切割到解釋&#xff0c;這里windows的txt文…