共有兩臺服務器A跟B,它們使用一條grpc長鏈接進行互動,A是grpc服務端,在公網;B是客戶端,在內網。 服務器A的代碼里有兩個協程,分別監聽http和grpc,用一個同步channel進行通信。
我的業務流程: 1、用戶通過http介面訪問A,A需要呼叫B的程式,此時使用Send(*Response) error把必要的引數發送過去; 2、B通過Recv()監聽到A發來的請示,把運算結果通過Send()發送回A; 3、A通過Recv()收到運算結果,把結果輸入到同步channel,http服務結束同步阻塞,回傳http response給用戶。
現在我要在步驟1加上30秒超時的限制,卻出現了奇怪的問題,偽代碼如下:
A.Send("data...")
go func() {
time.Sleep(30e9)
timeoutChan <- true
}()
select {
case <-timeoutChan:
// 回傳超時錯誤資訊
case resp := <-respChan:
// 正常回傳資料
}
按照我的想法,應該是用戶訪問A的http介面時,如果超過30秒,會得到個超時錯誤。但卻產生以下問題,有并發請示時(假設恰好請示1和請示2),請示1得到的http response是請示2的運算結果,請示2得到的http response是請示1的運算結果。
我回滾到原代碼,(即去掉了超時限制功能,沒有上邊的go func(){time.Sleep()}和select... case...),只使用同步channel一直阻塞等待回傳結果,進行壓力測驗,并不會出上以上問題,http request跟response都能對應。所以現在想不通,為何select... case...會出現以上問題,我需要做什么改進。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/183164.html
標籤:go語言
上一篇:攤牌了,我要手寫一個RPC
下一篇:請高手幫忙!
