Go實(shí)現(xiàn)超時(shí)控制的具體使用
應(yīng)用場(chǎng)景
交易、金融等事務(wù)系統(tǒng)往往會(huì)有各種下游,絕大多數(shù)時(shí)候我們會(huì)以同步方式進(jìn)行訪問,如調(diào)用RPC、HTTP等。 這些下游在通常延時(shí)相對(duì)穩(wěn)定,但有時(shí)可能出現(xiàn)極端的超大延時(shí),這些極端case可能具備特定的業(yè)務(wù)特征,也有可能單純是硬件、網(wǎng)絡(luò)的問題造成,最終表現(xiàn)在系統(tǒng)P99或者P999的延時(shí)出現(xiàn)了突刺,如果是面向C端的場(chǎng)景,也會(huì)向用戶報(bào)出一些系統(tǒng)錯(cuò)誤,造成用戶體驗(yàn)的下降。 一種簡(jiǎn)易的解決方案是,針對(duì)關(guān)鍵的下游節(jié)點(diǎn)增加超時(shí)控制。在特定時(shí)間內(nèi),如果下游到期還未返回,不再暴露系統(tǒng)級(jí)錯(cuò)誤,而是做特殊化處理,比如返回「處理中」?fàn)顟B(tài)。
Go實(shí)現(xiàn)方案
設(shè)計(jì)一個(gè)方法,使用閉包,傳入時(shí)間和執(zhí)行的任務(wù),如果任務(wù)執(zhí)行完未到時(shí)間,則直接返回,否則通知調(diào)用者超時(shí)。 為了保證代碼簡(jiǎn)介和使用簡(jiǎn)單,我們僅定義一個(gè)Wrapper方法,方法定義如下 func TimeoutControlWrapper(duration time.Duration, fn func()) (timeout bool)
官方包time有一個(gè)After方法,可以在指定時(shí)間內(nèi),返回一個(gè)channel,基于此來(lái)判斷是否超時(shí)。 另外,在Wrapper方法里異步化執(zhí)行目標(biāo)方法,執(zhí)行完成后寫入一個(gè)finish信號(hào)通知。 同時(shí)監(jiān)聽這兩個(gè)channel,判斷是否超時(shí),代碼如下
func TimeoutControlWrapper(duration time.Duration, fn func()) (timeout bool) {
finish := make(chan struct{})
go func() {
fn()
finish <- struct{}{}
}()
select {
case <-finish:
return false
case <-time.After(duration):
return true
}
}
結(jié)合場(chǎng)景,假設(shè)系統(tǒng)會(huì)調(diào)用一個(gè)支付系統(tǒng)的接口,接口本身延時(shí)不穩(wěn)定,因此我們套用TimeoutControlWrapper
func CallPaymentSystem(param PayParam) (payStatus PayStatus) {
var payStatus PayStatus
timeout := TimeoutControlWrapper(time.Second, func() {
payStatus = PaymentSystemRPC.Pay(param)
})
if timeout {
warn() // WARN告警
return PROCESSING // 返回處理中
}
return payStatus
}
延伸思考
上述通過一個(gè)簡(jiǎn)單的Wrapper,來(lái)實(shí)現(xiàn)調(diào)用下游時(shí)的超時(shí)控制。但在引入的場(chǎng)景里,實(shí)現(xiàn)上是不嚴(yán)謹(jǐn)?shù)摹D呐虏辉黾映瑫r(shí)控制,我們也無(wú)法確認(rèn)請(qǐng)求是否真實(shí)到達(dá)了下游系統(tǒng),這本質(zhì)上是一個(gè)分布式事務(wù)的問題,需要我們?cè)O(shè)計(jì)更加健全的系統(tǒng)能力保證一致性,比如通過消息的方式、補(bǔ)償機(jī)制、增加對(duì)賬系統(tǒng)。
到此這篇關(guān)于Go實(shí)現(xiàn)超時(shí)控制的具體使用的文章就介紹到這了,更多相關(guān)Go 超時(shí)控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang時(shí)間及時(shí)間戳的獲取轉(zhuǎn)換
本文主要介紹了golang時(shí)間及時(shí)間戳的獲取轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
Go語(yǔ)言編程實(shí)現(xiàn)支持六種級(jí)別的日志庫(kù)?
這篇文章主要為大家介紹了使用Golang編寫一個(gè)支持六種級(jí)別的日志庫(kù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Go語(yǔ)言遞歸函數(shù)的具體實(shí)現(xiàn)
本文主要介紹了Go語(yǔ)言遞歸函數(shù)的具體實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
Golang設(shè)計(jì)模式之單例模式詳細(xì)講解
單例模式很容易記住。就像名稱一樣,它只能提供對(duì)象的單一實(shí)例,保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問該實(shí)例的方法。本文就來(lái)聊聊Go語(yǔ)言中的單例模式,感興趣的小伙伴可以了解一下2023-01-01
Go語(yǔ)言中的自定義函數(shù)類型的實(shí)現(xiàn)
在Go語(yǔ)言中,函數(shù)類型是一種將函數(shù)作為值的數(shù)據(jù)類型,本文主要介紹了Go語(yǔ)言中的自定義函數(shù)類型,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09

