這篇文章主要為大家展示了“Netty發(fā)送隊列積壓導(dǎo)致內(nèi)存泄露怎么辦”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學習一下“Netty發(fā)送隊列積壓導(dǎo)致內(nèi)存泄露怎么辦”這篇文章吧。
成都創(chuàng)新互聯(lián)從2013年創(chuàng)立,先為拉孜等服務(wù)建站,拉孜等地企業(yè),進行企業(yè)商務(wù)咨詢服務(wù)。為拉孜企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
正文
導(dǎo)致Netty內(nèi)存泄漏的原因有很多,例如,使用內(nèi)存池創(chuàng)建的對象忘記釋放,或者對端系統(tǒng)服務(wù)壓力過大導(dǎo)致發(fā)送隊列積壓。
盡管Netty采用NIO非阻塞通信,I/O往往不是系統(tǒng)性能的瓶頸,但是如果服務(wù)端處理速度有限,客戶端發(fā)送數(shù)據(jù)量很大,沒有做好流控,同樣會導(dǎo)致內(nèi)存溢出。
對某個業(yè)務(wù)做性能壓測,基于Netty開發(fā)的多個客戶端并發(fā)鏈接一個服務(wù)端,客戶端運行一段時間后,內(nèi)存、CPU占用率居高不下,響應(yīng)越來越慢,最后自動宕機。
為了方便分析,這里簡化代碼,這里用一個死循環(huán)向服務(wù)端發(fā)送消息,模擬壓測環(huán)境,客戶端代碼如下:
Netty發(fā)送數(shù)據(jù)源碼分析
業(yè)務(wù)調(diào)用ChannelHandlerContext.write方法后,經(jīng)過ChannelPipeline責任鏈處理,消息被投遞到了發(fā)送緩沖區(qū)中待發(fā)送,調(diào)用flush后才真正發(fā)送。
writeAndFlush方法,內(nèi)部調(diào)用的是write方法,代碼如下
跟進write()方法,處理邏輯如下,首先判斷當前線程是否是NioEventLoop,如果不是,將發(fā)送的數(shù)據(jù)封裝成一個WriteTask,放入NioEventLoop的任務(wù)隊列由NioEventLoop線程執(zhí)行。
在execute里做同樣的判斷后,在這里走的是else分支,調(diào)用addTask()后,將任務(wù)添加到任務(wù)隊列中
Netty的NioEventLoop線程內(nèi)部維護了一個Queue
經(jīng)過一系列處理后,消費端在拿到數(shù)據(jù)后,最終會調(diào)用ChannelOutboundBuffer的addMessage方法,將消息加入到發(fā)送隊列。學過數(shù)據(jù)結(jié)構(gòu)的同學,可以很清楚的看到,這個發(fā)送隊列是基于鏈表組織起來的。
請注意方法結(jié)尾調(diào)用的incrementPendingOutboundByte方法,會在后面分析。文章開頭描述的現(xiàn)象與此方法有關(guān)。
如何防止發(fā)送隊列積壓
為了防止高并發(fā)場景下,由服務(wù)端處理慢導(dǎo)致客戶端消息積壓,除了服務(wù)端做流控外,客戶端也需要做流控,自身保護,方法是,設(shè)置待發(fā)送隊列的高低水位。
方法有兩種,第一種是在啟動類里設(shè)置option屬性
第二種是
當發(fā)送隊列到達高水位時,對應(yīng)的Channel就會變?yōu)椴豢蓪憼顟B(tài)。由于高水位并不影響業(yè)務(wù)線程調(diào)用write方法把消息寫入待發(fā)送隊列,因此必須在消息發(fā)送時對Channel的狀態(tài)進行判斷。
為了對待發(fā)送隊列發(fā)送速度的控制,Netty提供了高低水位的機制,當積壓消息量達到高水位時,修改Channel為不可寫狀態(tài),在ChannelOutboundBuffer類
修改Channel狀態(tài)后,調(diào)用ChannelPipeline發(fā)送通知消息
當積壓消息發(fā)送完成后,對低水位進行判斷,如果待發(fā)送字節(jié)數(shù)到達或低于低水位,修改Channel狀態(tài)為可寫,并發(fā)送通知事件。代碼如下
針對上述分析后,再回頭看文章開頭描述的問題,我們修改代碼為如下格式然后再壓測,允許一段時間后 ,系統(tǒng)穩(wěn)定。
內(nèi)存消耗如下,可見運行非常穩(wěn)定
以上是“Netty發(fā)送隊列積壓導(dǎo)致內(nèi)存泄露怎么辦”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!