Netty中遇到的問題:ctx.writeAndFlush造成非連續的請求。

目的

爲了保證客戶端的請求是順序發送到服務端的,ctx.writeAndFlush被包裝在用synchronized修飾的send方法中,客戶端統一調用sendRequest方法。

有多個線程使用sendRequest方法

1.eventLoop處理channelRead的結果,並調用sendRequest發送到服務端。
2.業務線程(如心跳線程,http請求對應的線程)去調用ctx.writeAndFlush
在這裏插入圖片描述

造成的後果

從客戶端看日誌是順序的,但是服務端總是收到非連續的請求。

代碼

服務端
檢測客戶端的請求cmdCnt,如果小於當前服務端的值,那麼就認爲是過期的命令
在這裏插入圖片描述

客戶端
同步的sendRequest方法,保證不同線程都是順序執行,cmdCnt順序增長。
除了EventLoop線程,業務線程也會調用到sendRequest
在這裏插入圖片描述
EventLoop線程執行sendRequest
在這裏插入圖片描述

原因

這是EventLoop的一個特性:【非EventLoop線程】調用ctx.writeAndFlush時,不會直接執行,而是放入taskQueue隊列中(等待之後eventLoop線程去執行)。

解決方法

全部改爲非業務線程去執行同步的sendRequest方法,去執行ctx.writeAndFlush,最終都提交給隊列。那麼順序提交到隊列,就順序取出發送到服務端。避免了EventLoop線程直接執行writeAndFlush。

解決問題的代碼
注意,內部的sendRequest纔是同步方法。
在這裏插入圖片描述

EventLoop處理任務流程

在這裏插入圖片描述
在這裏插入圖片描述

發佈了118 篇原創文章 · 獲贊 47 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章