Java開發Netty實戰分析之Tcp黏包/拆包解決方法

編程語言 Java Linux Facebook 圖靈學院 圖靈學院 2017-09-20

引言

Netty是目前業界最流行的NIO框架之一,它的健壯性、高性能、可定製和可擴展性在同類框架中都是首屈一指。它已經得到了成百上千的商業項目的驗證,例如Hadoop的RPC框架Avro就使用了Netty作為底層通信框架,其他的業界主流RPC框架,例如:Dubbo、Google 開源的gRPC、新浪微博開源的Motan、Twitter 開源的 finagle也使用Netty來構建高性能的異步通信能力。另外,阿里巴巴開源的消息中間件RocketMQ也使用Netty作為底層通信框架。

一丶TCP黏包/拆包

TCP是一個“流”協議,所謂流,就是沒有界限的一長串二進制數據。TCP作為傳輸層協議並不不瞭解上層業務數據的具體含義,它會根據TCP緩衝區的實際情況進行數據包的劃分,所以在業務上認為是一個完整的包,可能會被TCP拆分成多個包進行發送,也有可能把多個小的包封裝成一個大的數據包發送,這就是所謂的TCP粘包和拆包問題。

二丶Netty粘包和拆包解決方案

Netty提供了多個解碼器,可以進行分包的操作,分別是:

LineBasedFrameDecoder

DelimiterBasedFrameDecoder(添加特殊分隔符報文來分包)

FixedLengthFrameDecoder(使用定長的報文來分包) * LengthFieldBasedFrameDecoder

LineBasedFrameDecoder解碼器

LineBasedFrameDecoder是回車換行解碼器,如果用戶發送的消息以回車換行符作為消息結束的標識,則可以直接使用Netty的LineBasedFrameDecoder對消息進行解碼,只需要在初始化Netty服務端或者客戶端時將LineBasedFrameDecoder正確的添加到ChannelPipeline中即可,不需要自己重新實現一套換行解碼器。

1 inux 內核參數修改

Cannot assign requested address.”是由於linux分配的客戶端連接端口用盡,無法建立socket連接所致,雖然socket正常關閉,但是端口不是立即釋放,而是處於TIME_WAIT狀態,默認等待60s後才釋放。

vi /etc/sysctl.conf

#fs.file-max:表示文件句柄的最大數量。文件句柄表示在Linux系統中可以打開的文件數量。

fs.file-max = 1048576

#增加可用端口:

net.ipv4.ip_local_port_range = 1024 65535

net.ipv4.tcp_mem = 786432 2097152 3145728

net.ipv4.tcp_rmem = 4096 4096 16777216

net.ipv4.tcp_wmem = 4096 4096 16777216

#調低端口釋放後的等待時間,默認為60s,修改為15~30s

net.ipv4.tcp_fin_timeout=20

#修改tcp/ip協議配置, 通過配置/proc/sys/net/ipv4/tcp_tw_resue, 默認為0,修改為1,釋放TIME_WAIT端口給新連接使用

net.ipv4.tcp_tw_reuse = 1

#修改tcp/ip協議配置,快速回收socket資源,默認為0,修改為1

#net.ipv4.tcp_timestamps開啟,tw_recycle才會生效

net.ipv4.tcp_timestamps=1

net.ipv4.tcp_tw_recycle = 1

通過vi /etc/security/limits.conf 添加如下配置參數:修改之後保存,註銷當前用戶,重新登錄,通過

ulimit -a 查看修改的狀態是否生效。

soft  nofile  1000000

hard  nofile  1000000

通過 ulimit -a 查看最大句柄數

ulimit -n 10000000

改完後,執行命令“sysctl -p”使參數生效,不需要reboot。

三丶Netty簡介

不久以前,我們在本章一開始所呈現的場景——支持成千上萬的併發客戶端——還被認定為是不可能的。然而今天,作為系統用戶,我們將這種能力視為理所當然;同時作為開發人員,我們期望將水平線提得更高[3]。因為我們知道,總會有更高的吞吐量和可擴展性的要求——在更低的成本的基礎上進行交付。

不要低估了這最後一點的重要性。我們已經從漫長的痛苦經歷中學到:直接使用底層的API暴露了複雜性,並且引入了對往往供不應求的技能的關鍵性依賴[4]。這也就是,面向對象的基本概念:用較簡單的抽象隱藏底層實現的複雜性。

這一原則也催生了大量框架的開發,它們為常見的編程任務封裝瞭解決方案,其中的許多都和分佈式系統的開發密切相關。我們可以確定地說:所有專業的Java開發人員都至少對它們熟知一二。[5]對於我們許多人來說,它們已經變得不可或缺,因為它們既能滿足我們的技術需求,又能滿足我們的時間表。

在網絡編程領域,Netty是Java的卓越框架。[6]它駕馭了Java高級API的能力,並將其隱藏在一個易於使用的API之後。Netty使你可以專注於自己真正感興趣的——你的應用程序的獨一無二的價值。

在我們開始首次深入地瞭解Netty之前,請仔細審視表1-1中所總結的關鍵特性。有些是技術性的,而其他的更多的則是關於架構或設計哲學的。在本書的學習過程中,我們將不止一次地重新審視它們。

四丶Netty的特性總結

分  類

Netty的特性

設計

統一的API,支持多種傳輸類型,阻塞的和非阻塞的簡單而強大的線程模型真正的無連接數據報套接字支持鏈接邏輯組件以支持複用

易於使用

詳實的Javadoc和大量的示例集不需要超過JDK 1.6+[7]的依賴。(一些可選的特性可能需要Java 1.7+和/或額外的依賴)

性能

擁有比Java的核心API更高的吞吐量以及更低的延遲得益於池化和複用,擁有更低的資源消耗最少的內存複製

健壯性

不會因為慢速、快速或者超載的連接而導致OutOfMemoryError消除在高速網絡中NIO應用程序常見的不公平讀/寫比率

安全性

完整的SSL/TLS以及StartTLS支持可用於受限環境下,如Applet和OSGI

社區驅動

發佈快速而且頻繁

 五丶誰在使用Netty

Netty擁有一個充滿活力並且不斷壯大的用戶社區,其中不乏大型公司,如Apple、Twitter、Facebook、Google、Square和Instagram,還有流行的開源項目,如Infinispan、HornetQ、Vert.x、Apache Cassandra和Elasticsearch[8],它們所有的核心代碼都利用了Netty強大的網絡抽象[9]。在初創企業中,Firebase和Urban Airship也在使用Netty,前者用來做HTTP長連接,而後者用來支持各種各樣的推送通知。

每當你使用Twitter,你便是在使用Finagle[10],它們基於Netty的系統間通信框架。Facebook在Nifty中使用了Netty,它們的Apache Thrift服務。可伸縮性和性能對這兩家公司來說至關重要,他們也經常為Netty貢獻代碼[11]。

反過來,Netty也已從這些項目中受益,通過實現FTP、SMTP、HTTP和WebSocket以及其他的基於二進制和基於文本的協議,Netty擴展了它的應用範圍及靈活性。

總結

以 上就是我推薦以上是對Java開發Netty實戰分析之Tcp黏包/拆包解決方法問題及其優化總結,分享給大家,希望大家可以瞭解什麼是 Java開發Netty實戰分析之Tcp黏包/拆包解決方法問題及其優化。覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持

1、多寫多敲代碼,好的代碼與紮實的基礎知識一定是實踐出來的

2、可以去百度搜索騰訊課堂圖靈學院的視頻來學習一下java架構實戰案例,還挺不錯的。

最後,每一位讀到這裡的網友,感謝你們能耐心地看完。希望在成為一名更優秀的Java程序員的道路上,我們可以一起學習、一起進步。

3丶想了解學習以上課程內容可加群:469717771 驗證碼(06 必過) ~.~

Java開發Netty實戰分析之Tcp黏包/拆包解決方法

相關推薦

推薦中...