您好,登錄后才能下訂單哦!
本篇內容介紹了“如何使用Netty實現多路復用的client”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
Netty只提供的異步傳輸數據的方式,但是并沒有實現多路復用的client。
一個分布式的客戶端代碼基本是這個樣子的:
public Response sent(final Request request) { channel.writeAndFlush(request); return clientChannelInitializer.getResponse(request.getMessageId()); }
首先通過channel發送一個請求到server,然后等待server返回的結果。
但是Netty是異步的,writeAndFlush這個方法,只是告訴server,我要發數據了,然后就馬上返回了。所以這時直接調用getResponse,會得不到值。因為netty是在回調里面寫返回值的。
解決的辦法是,使用BlockingQueue接收返回的數據。一旦BlockingQueue有數據了,就take出來。如果沒數據,就一直等待。
在單線程里,這個辦法沒問題。這就要確保Netty的client只被一個線程訪問。如果是多線程同時訪問,因為異步的原因,有可能第二個線程的返回值被第一個線程拿到。舉個例子:
線程A使用client發送請求
線程A從BlockingQueue中取數據。這時Queue為空,線程A等待。
server接受并開啟一個線程處理請求A
線程B使用client發送請求
線程B從BlockingQueue中取數據。這時Queue為空,線程B也等待。
server接受并開啟另一個線程處理請求B
線程B的請求處理速度較快,先返回
client將返回值B寫入BlockingQueue
BlockQueue有數據了,線程A take到數據,但是是線程B的結果
這就導致request和response不匹配。
要解決這個問題有3個辦法。
使用短連接,每次請求new一個client,接收的response后close掉這個client。這個的缺點很明顯,這就相當于http服務器了,不能發揮內網長連接的優勢。
使用連接池,每次從連接池里拿一個client,接收完response后將這個client返還連接池。這個就有點像數據庫連接池。這個方法沒什么缺點,但是需要自己實現連接池。
使用單一client,但是在request中生成一個唯一的messageId,可以是nanoTime。然后server處理完后,在response中也返回這個messageId。這樣在client不是維護一個BlockingQueue,而是維護一個ConcurrentHashMap,key是messageId,value是一個空的BlockingQueue。當client發送resquest到server時,在Map里寫入messageId,并實例化一個BlockingQueue(為了優化,size可以是1)。然后等待這個BlockingQueue有值。在接收到response的回調方法里,根據messageId取出blockingQueue的值,然后刪除掉這個Key。
我自己實現了第三種方式,具體代碼請參見:
https://github.com/terrymanu/miracle-framework/tree/master/miracle-framework-remote/miracle-framework-remote-netty
“如何使用Netty實現多路復用的client”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。