溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用Netty實(shí)現(xiàn)多路復(fù)用的client

發(fā)布時(shí)間:2021-07-27 22:17:39 來(lái)源:億速云 閱讀:427 作者:chen 欄目:云計(jì)算

本篇內(nèi)容介紹了“如何使用Netty實(shí)現(xiàn)多路復(fù)用的client”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Netty只提供的異步傳輸數(shù)據(jù)的方式,但是并沒(méi)有實(shí)現(xiàn)多路復(fù)用的client。

一個(gè)分布式的客戶端代碼基本是這個(gè)樣子的:

public Response sent(final Request request) {
    channel.writeAndFlush(request);		
    return clientChannelInitializer.getResponse(request.getMessageId());	
}

首先通過(guò)channel發(fā)送一個(gè)請(qǐng)求到server,然后等待server返回的結(jié)果。

但是Netty是異步的,writeAndFlush這個(gè)方法,只是告訴server,我要發(fā)數(shù)據(jù)了,然后就馬上返回了。所以這時(shí)直接調(diào)用getResponse,會(huì)得不到值。因?yàn)閚etty是在回調(diào)里面寫返回值的。

解決的辦法是,使用BlockingQueue接收返回的數(shù)據(jù)。一旦BlockingQueue有數(shù)據(jù)了,就take出來(lái)。如果沒(méi)數(shù)據(jù),就一直等待。

在單線程里,這個(gè)辦法沒(méi)問(wèn)題。這就要確保Netty的client只被一個(gè)線程訪問(wèn)。如果是多線程同時(shí)訪問(wèn),因?yàn)楫惒降脑?,有可能第二個(gè)線程的返回值被第一個(gè)線程拿到。舉個(gè)例子:

  1. 線程A使用client發(fā)送請(qǐng)求

  2. 線程A從BlockingQueue中取數(shù)據(jù)。這時(shí)Queue為空,線程A等待。

  3. server接受并開啟一個(gè)線程處理請(qǐng)求A

  4. 線程B使用client發(fā)送請(qǐng)求

  5. 線程B從BlockingQueue中取數(shù)據(jù)。這時(shí)Queue為空,線程B也等待。

  6. server接受并開啟另一個(gè)線程處理請(qǐng)求B

  7. 線程B的請(qǐng)求處理速度較快,先返回

  8. client將返回值B寫入BlockingQueue

  9. BlockQueue有數(shù)據(jù)了,線程A take到數(shù)據(jù),但是是線程B的結(jié)果

這就導(dǎo)致request和response不匹配。

要解決這個(gè)問(wèn)題有3個(gè)辦法。

  1. 使用短連接,每次請(qǐng)求new一個(gè)client,接收的response后close掉這個(gè)client。這個(gè)的缺點(diǎn)很明顯,這就相當(dāng)于http服務(wù)器了,不能發(fā)揮內(nèi)網(wǎng)長(zhǎng)連接的優(yōu)勢(shì)。

  2. 使用連接池,每次從連接池里拿一個(gè)client,接收完response后將這個(gè)client返還連接池。這個(gè)就有點(diǎn)像數(shù)據(jù)庫(kù)連接池。這個(gè)方法沒(méi)什么缺點(diǎn),但是需要自己實(shí)現(xiàn)連接池。

  3. 使用單一client,但是在request中生成一個(gè)唯一的messageId,可以是nanoTime。然后server處理完后,在response中也返回這個(gè)messageId。這樣在client不是維護(hù)一個(gè)BlockingQueue,而是維護(hù)一個(gè)ConcurrentHashMap,key是messageId,value是一個(gè)空的BlockingQueue。當(dāng)client發(fā)送resquest到server時(shí),在Map里寫入messageId,并實(shí)例化一個(gè)BlockingQueue(為了優(yōu)化,size可以是1)。然后等待這個(gè)BlockingQueue有值。在接收到response的回調(diào)方法里,根據(jù)messageId取出blockingQueue的值,然后刪除掉這個(gè)Key。

    我自己實(shí)現(xiàn)了第三種方式,具體代碼請(qǐng)參見(jiàn):

    https://github.com/terrymanu/miracle-framework/tree/master/miracle-framework-remote/miracle-framework-remote-netty 

“如何使用Netty實(shí)現(xiàn)多路復(fù)用的client”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI