問(wèn)題:
高并發(fā)大壓力下發(fā)現(xiàn)TOP平臺(tái)消息會(huì)出現(xiàn)消息串掉,
先說(shuō)一下具體的原因:
數(shù)據(jù)交互中,其中一方單獨(dú)認(rèn)為業(yè)務(wù)交互失敗,邏輯回收而非物理關(guān)閉復(fù)用的信道,另一方在完成業(yè)務(wù)操作時(shí)將業(yè)務(wù)數(shù)據(jù)再次推送到已經(jīng)被邏輯回收的通道上,會(huì)導(dǎo)致請(qǐng)求和相應(yīng)錯(cuò)位。
代碼層設(shè)計(jì)問(wèn)題:
1. 信道一次業(yè)務(wù)交互中的多次消息交互缺少唯一的會(huì)話碼,導(dǎo)致中間任何一次交互出現(xiàn)問(wèn)題,后續(xù)的數(shù)據(jù)會(huì)錯(cuò)位到后續(xù)復(fù)用此信道其他請(qǐng)求中。
2. 底層信道的回收,異常處理,沒(méi)有在信道層直接處理,而是將錯(cuò)誤通過(guò)業(yè)務(wù)堆棧拋到最外層ajp協(xié)議解析線程管理池去做,導(dǎo)致不論是業(yè)務(wù)捕獲異常或者是servlet,spring框架捕獲異常都會(huì)出現(xiàn)串號(hào)。
解決方法:
1. 在協(xié)議層增加會(huì)話碼,發(fā)現(xiàn)會(huì)話錯(cuò)位,關(guān)閉信道。
2. 讓底層信道出現(xiàn)異常自己回收和關(guān)閉信道,連接池獲取連接的時(shí)候判斷連接是否已經(jīng)無(wú)效,無(wú)效即刻移除。(不需要用拋錯(cuò)誤堆棧的方式來(lái)實(shí)現(xiàn))
后續(xù):
TOP這邊已經(jīng)在考慮異步Web request請(qǐng)求處理的方式,后續(xù)在安全的要求下可以和nginx 做類(lèi)似信道復(fù)用的web服務(wù)器+應(yīng)用服務(wù)器的模式。
詳細(xì)說(shuō)明看下面的內(nèi)容:
用兩張圖片說(shuō)明問(wèn)題。
第一張是一次請(qǐng)求在JK和Jboss-web之間的交互過(guò)程。

問(wèn)題發(fā)生在第四步,在jboss-web向JK請(qǐng)求body的數(shù)據(jù)的時(shí)候可能產(chǎn)生超時(shí)或者其他IO異常,這時(shí)候直接會(huì)走到9這步,由于異常被捕獲,連接將不會(huì)被物理關(guān)閉。

一次請(qǐng)求處理的調(diào)用順序如上,按照數(shù)字順序,當(dāng)在5出現(xiàn)問(wèn)題的時(shí)候,AjpAprProcessor沒(méi)有自己物理關(guān)閉,而是依賴異常上拋的方式,返回到ajpAprProtocal來(lái)關(guān)閉AjpAprProcessor。簡(jiǎn)單來(lái)做就只需要在5就地處理,關(guān)閉連接,雖然會(huì)被放入連接池,但是只要在2這個(gè)步驟使用連接池的時(shí)候檢查一下連接狀態(tài)就可以丟棄這些無(wú)效的連接。