Golang三種方式實現超時退出

2022-01-19 11:59:40 字數 1925 閱讀 8508

前段時間發現線上有個服務介面,總是間歇性告警,有時候一天兩三次,有時候一天都沒有。

告警的邏輯是在乙個介面中非同步呼叫了另乙個http介面,這個http介面呼叫出現超時。但是我去問了負責這個http介面的同學,人家說他們的介面相應都是毫秒級別,還截圖監控了,有圖有真相,我還能說啥。

但是,超時是確實存在的,只是請求還可能沒有到人家服務那邊。

這種偶發性問題不好復現,偶爾來個告警也挺煩的,第一反應還是先解決問題,思路也簡單,失敗後重試。

且不談重試策略,先說說什麼時候觸發重試。

我們可以在介面請求出錯丟擲err的時候重試,但是這種不好控制,如果乙個請求出去,十來秒都沒有響應,則這個協程就要傻傻的等他報錯才能重試,浪費生命啊~

所以結合上面同學給出的毫秒級響應指標,可以設定乙個超時時間,如果在指定超時時間後沒有返回結果,則重試(這篇重試不是重點)。

func asynccall() (ctx)

select

}

說明1、通過context的withtimeout設定乙個有效時間為800毫秒的context。

2、該context會在耗盡800毫秒後或者方法執行完成後結束,結束的時候會向通道ctx.done傳送訊號。

3、有人可能要問,你這裡已經設定了context的有效時間,為什麼還要加上這個time.after呢?

這是因為該方法內的context是自己申明的,可以手動設定對應的超時時間,但是在大多數場景,這裡的ctx是從上游一直傳遞過來的,對於上游傳遞過來的context還剩多少時間,我們是不知道的,所以這時候通過time.after設定乙個自己預期的超時時間就很有必要了。

4、注意,這裡要記得呼叫cancel(),不然即使提前執行完了,還要傻傻等到800毫秒後context才會被釋放。

總結

上面的超時控制是搭配使用了ctx.done和time.after。

done通道負責監聽context啥時候完事,如果在time.after設定的超時時間到了,你還沒完事,那我就不等了,執行超時後的邏輯**。

那麼,除了上面這種超時控制策略,還有其他的套路嗎?

有,但是大同小異。

第一種:使用time.newtimer

func asynccall() (ctx)

select

}

這裡的主要區別是將time.after換成了time.newtimer,也是同樣的思路如果介面呼叫提前完成,則監聽到done訊號,然後關閉定時器。

否則的話,會在指定的timer即900毫秒後執行超時後的業務邏輯。

第二種:使用通道

func asynccall() , 1)

go func(ctx context.context) {}

}(ctx)

select

}

1、這裡主要利用通道可以在協程之間通訊的特點,當呼叫成功後,向done通道傳送訊號。

2、監聽done訊號,如果在time.after超時時間之前接收到,則正常返回,否則走向time.after的超時邏輯,執行超時邏輯**。

3、這裡使用的是通道和time.after組合,也可以使用通道和time.newtimer組合。

本篇主要介紹如何實現超時控制,主要有三種

Golang實現超時退出的三種方式

前段時間發現線上有個服務介面,總是間歇性告警,有時候一天兩三次,有時候一天都沒有。告警的邏輯是在乙個介面中非同步呼叫了另乙個http介面,這個http介面呼叫出現超時。但是我去問了負責這個http介面的同學,人家說他們的介面相應都是毫秒級別,還截圖監控了,有圖有真相,我還能說啥。但是,超時是確實存在...

Golang 變數申明的三種方式

golang 申明變數主要有三種方式 一是使用 var 關鍵字,申明包級或函式級變數 二是使用短變數申明方式,只能申明函式級變數,且需指明變數值 三是使用 const 關鍵字,申明包級或函式級常量。1.var var 可以申明包級變數,短變程式設計客棧量申明方式不可以,這是二者最大的區別。var n...

json三種實現方式

size large 使用ajax的開發專案過程中,經常需要將json格式的字串返回到前端,前端解析成js物件 json ecma 262 e3 中沒有將json概念寫到標準中,還好在 ecma 262 e5 中json的概念被正式引入了,包括全域性的json物件和date的tojson方法。1,e...