本文目錄一覽:
- 1、golang之context詳解
- 2、golang中有什麼方法可以在控制器中設置http超時時間
- 3、golang channel 超時如何處理
- 4、golang http server如何設置request的context超時
- 5、golang sync.mutex 超時select
- 6、golang對etcd的簡單操作
golang之context詳解
為什麼需要context
在go服務器中,對於每個請求的request都是在單獨的goroutine中進行的,處理一個request也可能設計多個goroutine之間的交互, 使用context可以使開發者方便的在這些goroutine里傳遞request相關的數據、取消goroutine的signal或截止日期
在並發程序中,由於超時、取消操作或者一些異常情況,往往需要進行搶佔操作或者中斷後續操作。熟悉channel的朋友應該都見過使用done channel來處理此類問題。比如以下這個例子:
上述例子中定義了一個buffer為0的channel done, 子協程運行着定時任務。如果主協程需要在某個時刻發送消息通知子協程中斷任務退出,那麼就可以讓子協程監聽這個done channel,一旦主協程關閉done channel,那麼子協程就可以推出了,這樣就實現了主協程通知子協程的需求。這很好,但是這也是有限的。
如果我們可以在簡單的通知上附加傳遞額外的信息來控制取消:為什麼取消,或者有一個它必須要完成的最終期限,更或者有多個取消選項,我們需要根據額外的信息來判斷選擇執行哪個取消選項。
考慮下面這種情況:假如主協程中有多個任務1, 2, …m,主協程對這些任務有超時控制;而其中任務1又有多個子任務1, 2, …n,任務1對這些子任務也有自己的超時控制,那麼這些子任務既要感知主協程的取消信號,也需要感知任務1的取消信號。
如果還是使用done channel的用法,我們需要定義兩個done channel,子任務們需要同時監聽這兩個done channel。嗯,這樣其實好像也還行哈。但是如果層級更深,如果這些子任務還有子任務,那麼使用done channel的方式將會變得非常繁瑣且混亂。
我們需要一種優雅的方案來實現這樣一種機制:
上層任務取消後,所有的下層任務都會被取消;中間某一層的任務取消後,只會將當前任務的下層任務取消,而不會影響上層的任務以及同級任務。
這個時候context就派上用場了。我們首先看看context的結構設計和實現原理。
context接口
先看Context接口結構,看起來非常簡單。
}
Context接口包含四個方法:
Deadline返回綁定當前context的任務被取消的截止時間;如果沒有設定期限,將返回ok == false。
Done 當綁定當前context的任務被取消時,將返回一個關閉的channel;如果當前context不會被取消,將返回nil。
Err 如果Done返回的channel沒有關閉,將返回nil;如果Done返回的channel已經關閉,將返回非空的值表示任務結束的原因。如果是context被取消,Err將返回Canceled;如果是context超時,Err將返回DeadlineExceeded。
Value 返回context存儲的鍵值對中當前key對應的值,如果沒有對應的key,則返回nil。
可以看到Done方法返回的channel正是用來傳遞結束信號以搶佔並中斷當前任務;Deadline方法指示一段時間後當前goroutine是否會被取消;以及一個Err方法,來解釋goroutine被取消的原因;而Value則用於獲取特定於當前任務樹的額外信息。而context所包含的額外信息鍵值對是如何存儲的呢?其實可以想象一顆樹,樹的每個節點可能攜帶一組鍵值對,如果當前節點上無法找到key所對應的值,就會向上去父節點裡找,直到根節點。
emptyCtx
emptyCtx是一個int類型的變量,但實現了context的接口。emptyCtx沒有超時時間,不能取消,也不能存儲任何額外信息,所以emptyCtx用來作為context樹的根節點。
Background和TODO只是用於不同場景下: Background通常被用於主函數、初始化以及測試中,作為一個頂層的context,也就是說一般我們創建的context都是基於Background;而TODO是在不確定使用什麼context的時候才會使用。
用法 :
golang中有什麼方法可以在控制器中設置http超時時間
可以設置一個定時器,定時執行panic,控制器執行完畢取消定時器,然後recover判斷是否超時panic,是則返回408錯誤。
上面是比較取巧的一種方式,正規一點應該是定義一個transport中間層,數據通過這個中間層傳輸,這樣可以很好的控制傳輸過程,定時完全沒問題。
golang channel 超時如何處理
個人理解的channel超時處理思路分享,若有錯誤或者不足,請聯繫我:qq 869329877
主程序通過go timeout()掛起一個協程,在timeout方法裡面利用select來監控邏輯處理的變化,如果請求時間過長或者連接到其他服務比如grpc、mysql等服務中斷導致的請求時間過長,則直接超時,超時要返回定義的管道數據結果,否則程序會報錯。
golang http server如何設置request的context超時
main函數
handler函數
在handler函數裡面從r.Context生成一個新的context,並傳遞給功能函數GetUser(ctx context).
功能函數
在功能函數裡面,異步方式調用起來具體的實現功能,然後等待在ctx.Done()或者c裡面有數據。
使用curl工具發起client請求:
golang sync.mutex 超時select
做了一個參考實例。假設某線程佔用時間5秒,超時時間為2秒
func mian() {
lock := sync.Mutex{}
lock.Lock()
defer lock.Unlock()
timer := time.NewTimer(2 * time.Second)
end:=make(chan int)
go func() {
time.Sleep(5*time.Second)
fmt.Println(“wait”)
end-1
}()
select {
case -end:
case -timer.C:
}
fmt.Println(“End”)
}
golang對etcd的簡單操作
首先獲取clientv3:
連接etcd:
kv是一個用於操作kv的連接,其實它本質上是用了client的conn,為了更加專註於鍵值對的操作,關閉client後也會使kv無法用。(kv的操作client也能實現)
設置一個超時的context:
context.WithTimeout()會返回一個timerCtx{},並在這個結構體里注入了超時時間。cancleFunc是一個取消操作的函數。put,get等操作是阻塞型操作,context里有一個用於管理超時的select,當時間一到就會隱式執行cancelFunc,使操作停止並返回錯誤。如果顯式的調用cancelFunc()則會立即停止操作,返回錯誤。
put操作:
由於etcd是有序存儲鍵值對的,還可以附加clientv3.WithFromKey(),clientv3.WithLimit()來實現分頁獲取的效果。
監聽etcd集群鍵的改變:
原創文章,作者:MMKWS,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/329832.html