最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go-zero過載保護(hù)源碼解讀

 更新時間:2023年08月10日 11:11:51   作者:TTSimple  
這篇文章主要為大家介紹了go-zero過載保護(hù)源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

在看文章之前可以看看萬總的這篇文章《服務(wù)自適應(yīng)降載保護(hù)設(shè)計》,文章已經(jīng)給我們介紹很清楚了,從基礎(chǔ)原理到架構(gòu)需求再到代碼注釋,無不細(xì)致入微,感謝萬總。

之前在設(shè)計架構(gòu)的時候?qū)τ诜?wù)過載保護(hù)只會想到在客戶端、網(wǎng)關(guān)層來實現(xiàn),沒考慮過在服務(wù)端也可以達(dá)到這種效果,一來涉及這種技術(shù)的文章較少(可能是我孤陋寡聞了),二來服務(wù)端不確定的情況比較多,比如服務(wù)器出現(xiàn)問題,或者其他在同一臺服務(wù)器運行的軟件把服務(wù)器直接搞掛,這樣在服務(wù)端實現(xiàn)過載保護(hù)在某些層面來說魯棒性可能不太好 ,但在和熔斷器結(jié)合后,用服務(wù)端來實現(xiàn)過載保護(hù)也是合情合理的。

我們來看下過載保護(hù)設(shè)計到的幾個算法

自旋鎖

  • 原理

問:假設(shè)有1個變量lock,2個協(xié)程怎么用鎖實現(xiàn)lock++,lock的結(jié)果最后為2

答:

  • 鎖也是1個變量,初值設(shè)為0;
  • 1個協(xié)程將鎖原子性的置為1;
  • 操作變量lock;
  • 操作完成后,將鎖原子性的置為0,釋放鎖。
  • 在1個協(xié)程獲取鎖時,另一個協(xié)程一直嘗試,直到能夠獲取鎖(不斷循環(huán)),這就是自旋鎖。

自旋鎖的缺點

  • 某個協(xié)程持有鎖時間長,等待的協(xié)程一直在循環(huán)等待,消耗CPU資源。
  • 不公平,有可能存在有的協(xié)程等待時間過程,出現(xiàn)線程饑餓(這里就是協(xié)程饑餓)

go-zero 自旋鎖源碼

type SpinLock struct {
    // 鎖變量
    lock uint32
}
// Lock locks the SpinLock.
func (sl *SpinLock) Lock() {
    for !sl.TryLock() {
        // 暫停當(dāng)前goroutine,讓其他goroutine先行運算
        runtime.Gosched()
    }
}
// TryLock tries to lock the SpinLock.
func (sl *SpinLock) TryLock() bool {
    // 原子交換,0換成1
    return atomic.CompareAndSwapUint32(&sl.lock, 0, 1)
}
// Unlock unlocks the SpinLock.
func (sl *SpinLock) Unlock() {
    // 原子置零
    atomic.StoreUint32(&sl.lock, 0)
}

源碼中還使用了 golang 的運行時操作包 runtime

runtime.Gosched()暫停當(dāng)前goroutine,讓其他goroutine先行運算

注意:只是暫停,不是掛起。

當(dāng)時間片輪轉(zhuǎn)到該協(xié)程時,Gosched()后面的操作將自動恢復(fù)

我們來寫寫幾行代碼,看看他的作用是啥

func output(s string) {
    for i := 0; i < 3; i++ {
        fmt.Println(s)
    }
}
// 未使用Gosched的代碼
func Test_GoschedDisable(t *testing.T) {
    go output("goroutine 2")
    output("goroutine 1")
}
// === RUN   Test_GoschedDisable
// goroutine 1
// goroutine 1
// goroutine 1
// --- PASS: Test_GoschedDisable (0.00s)

小結(jié)

還沒等到子協(xié)程執(zhí)行,主協(xié)程就已經(jīng)執(zhí)行完退出了,子協(xié)程將不再執(zhí)行,所以打印的全部是主協(xié)程的數(shù)據(jù)。當(dāng)然,實際上這個執(zhí)行結(jié)果也是不確定的,只是大概率出現(xiàn)以上輸出,因為主協(xié)程和子協(xié)程間并沒有絕對的順序關(guān)系

func output(s string) {
    for i := 0; i < 3; i++ {
        fmt.Println(s)
    }
}
// 使用Gosched的代碼
func Test_GoschedEnable(t *testing.T) {
    go output("goroutine 2")
    runtime.Gosched()
    output("goroutine 1")
}
// === RUN   Test_GoschedEnable
// goroutine 2
// goroutine 2
// goroutine 2
// goroutine 1
// goroutine 1
// goroutine 1
// --- PASS: Test_GoschedEnable (0.00s)

結(jié)論:在打印goroutine 1之前,主協(xié)程調(diào)用了runtime.Gosched()方法,暫停了主協(xié)程。子協(xié)程獲得了調(diào)度,從而先行打印了goroutine 2。主協(xié)程不是一定要等其他協(xié)程執(zhí)行完才會繼續(xù)執(zhí)行,而是一定時間。如果這個時間內(nèi)其他協(xié)程沒有執(zhí)行完,那么主協(xié)程將繼續(xù)執(zhí)行,例如以下例子

func output(s string) {
    for i := 0; i < 3; i++ {
        fmt.Println(s)
    }
}
// 使用Gosched的代碼,并故意延長子協(xié)程的執(zhí)行時間,看主協(xié)程是否一直等待
func Test_GoschedEnableAndSleep(t *testing.T) {
    go func() {
        time.Sleep(5000)
        output("goroutine 2")
    }()
    runtime.Gosched()
    output("goroutine 1")
}
// === RUN   Test_GoschedEnableAndSleep
// goroutine 2
// goroutine 2
// goroutine 2
// goroutine 1
// goroutine 1
// goroutine 1
// --- PASS: Test_GoschedEnableAndSleep (0.00s)

結(jié)論:即使我們故意延長子協(xié)程的執(zhí)行時間,主協(xié)程還是會一直等待子協(xié)程執(zhí)行完才會執(zhí)行。

源碼中還使用了 golang 的原子操作包 atomic

atomic.CompareAndSwapUint32()函數(shù)用于對uint32值執(zhí)行比較和交換操作,此函數(shù)是并發(fā)安全的。

// addr 表示地址
// old  表示uint32值,它是舊的,
// new  表示uint32新值,它將與舊值交換自身。
// 如果交換完成,則返回true,否則返回false。
func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)

atomic.StoreUint32() 函數(shù)用于將val原子存儲到* addr中,此函數(shù)是并發(fā)安全的。

// addr 表示地址
// val  表示uint32值,它是舊的,
func StoreUint32(addr *uint32, val uint32)

過載保護(hù)核心還使用了滑動窗口,滑動窗口的原理和細(xì)節(jié)可以看前一篇文章,里面有詳細(xì)解答。

以上就是go-zero過載保護(hù)源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于go-zero過載保護(hù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • golang實現(xiàn)java uuid的序列化方法

    golang實現(xiàn)java uuid的序列化方法

    這篇文章主要介紹了golang實現(xiàn)java uuid的序列化方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • golang MarshalJson的實現(xiàn)

    golang MarshalJson的實現(xiàn)

    本文主要介紹了golang MarshalJson的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • 如何解析golang中Context在HTTP服務(wù)中的角色

    如何解析golang中Context在HTTP服務(wù)中的角色

    這篇文章主要介紹了如何解析golang中Context在HTTP服務(wù)中的角色問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 一文帶你了解Go語言fmt標(biāo)準(zhǔn)庫輸出函數(shù)的使用

    一文帶你了解Go語言fmt標(biāo)準(zhǔn)庫輸出函數(shù)的使用

    這篇文章主要為大家詳細(xì)介紹了Go語言中 fmt 標(biāo)準(zhǔn)庫輸出函數(shù)的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • GoLang之標(biāo)準(zhǔn)庫encoding/json包

    GoLang之標(biāo)準(zhǔn)庫encoding/json包

    本文主要介紹了GoLang之標(biāo)準(zhǔn)庫encoding/json包,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Go語言什么時候該使用指針

    Go語言什么時候該使用指針

    本文主要介紹了Go語言什么情況下應(yīng)該使用指針,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Goland中Protobuf的安裝、配置和使用

    Goland中Protobuf的安裝、配置和使用

    本文記錄了mac環(huán)境下protobuf的編譯安裝,并通過一個示例來演示proto自動生成go代碼,本文使用的mac?os?12.3系統(tǒng),不建議使用homebrew安裝,系統(tǒng)版本太高,會安裝報錯,所以自己下載新版壓縮包編譯構(gòu)建安裝
    2022-05-05
  • Go語言并發(fā)編程 互斥鎖詳情

    Go語言并發(fā)編程 互斥鎖詳情

    在并發(fā)編程中,多個Goroutine訪問同一塊內(nèi)存資源時可能會出現(xiàn)競態(tài)條件,我們需要在臨界區(qū)中使用適當(dāng)?shù)耐讲僮鱽硪员苊飧倯B(tài)條件。Go 語言中提供了很多同步工具,本文將介紹互斥鎖Mutex和讀寫鎖RWMutex的使用方法。
    2021-10-10
  • Go語言循環(huán)遍歷含有中文的字符串的方法小結(jié)

    Go語言循環(huán)遍歷含有中文的字符串的方法小結(jié)

    這篇文章主要介紹了Go語言循環(huán)遍歷含有中文的字符串的幾種方法,文章通過代碼示例講解的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07
  • gin 獲取post請求的json body操作

    gin 獲取post請求的json body操作

    這篇文章主要介紹了gin 獲取post請求的json body操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03

最新評論

西华县| 璧山县| 杭锦后旗| 讷河市| 蒙城县| 临夏县| 三门县| 漾濞| 平乐县| 遵义市| 芮城县| 怀来县| 志丹县| 松潘县| 黄陵县| 澄城县| 苏尼特左旗| 慈利县| 陵川县| 北安市| 万年县| 桃源县| 诏安县| 大安市| 阜新市| 邹城市| 永仁县| 浦县| 灵寿县| 拉萨市| 安庆市| 普兰店市| 青海省| 正镶白旗| 敖汉旗| 琼结县| 平潭县| 林西县| 宁远县| 合水县| 呼玛县|