中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

hystrix-go怎么用-創(chuàng)新互聯(lián)

小編給大家分享一下hystrix-go怎么用,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

10年積累的成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站策劃后付款的網(wǎng)站建設(shè)流程,更有宿州免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

開篇


這周在看內(nèi)部一個(gè)熔斷限流包時(shí),發(fā)現(xiàn)它是基于一個(gè)開源項(xiàng)目hystrix-go 實(shí)現(xiàn)了,因此有了這篇文章。

Hystrix

Hystrix 是由Netflex 開發(fā)的一款開源組件,提供了基礎(chǔ)的熔斷功能。Hystrix 將降級(jí)的策略封裝在Command 中,提供了runfallback 兩個(gè)方法,前者表示正常的邏輯,比如微服務(wù)之間的調(diào)用……,如果發(fā)生了故障,再執(zhí)行fallback方法返回結(jié)果,我們可以把它理解成保底操作。如果正常邏輯在短時(shí)間內(nèi)頻繁發(fā)生故障,那么可能會(huì)觸發(fā)短路,也就是之后的請(qǐng)求不再執(zhí)行run,而是直接執(zhí)行  fallback。更多關(guān)于Hystrix 的信息可以查看https://github.com/Netflix/Hystrix,而
hystrix-go 則是用go 實(shí)現(xiàn)的hystrix 版,更確切的說,是簡(jiǎn)化版。只是上一次更新還是 2018年 的一次pr,也就畢業(yè)了?

為什么需要這些工具?
比如一個(gè)微服務(wù)化的產(chǎn)品線上,每一個(gè)服務(wù)都專注于自己的業(yè)務(wù),并對(duì)外提供相應(yīng)的服務(wù)接口,或者依賴于外部服務(wù)的某個(gè)邏輯接口,就像下面這樣。
hystrix-go怎么用

假設(shè)我們當(dāng)前是服務(wù)A,有部分邏輯依賴于服務(wù)C,服務(wù)C 又依賴于服務(wù)E,當(dāng)前微服務(wù)之間進(jìn)行rpc或者http通信,假設(shè)此時(shí)服務(wù)C 調(diào)用 服務(wù)E 失敗,比如由于網(wǎng)絡(luò)波動(dòng)導(dǎo)致超時(shí)或者服務(wù)E由于過載,系統(tǒng)E 已經(jīng)down掉了。
hystrix-go怎么用

調(diào)用失敗,一般會(huì)有失敗重試等機(jī)制。但是再想想,假設(shè)服務(wù)E已然不可用的情況下,此時(shí)新的調(diào)用不斷產(chǎn)生,同時(shí)伴隨著調(diào)用等待和失敗重試,會(huì)導(dǎo)致 服務(wù)C對(duì)服務(wù)E的調(diào)用而產(chǎn)生大量的積壓,慢慢會(huì)耗盡服務(wù)C的資源,進(jìn)而導(dǎo)致服務(wù)C也down掉,這樣惡性循環(huán)下,會(huì)影響到整個(gè)微服務(wù)體系,產(chǎn)生雪崩效應(yīng)。
hystrix-go怎么用

雖然導(dǎo)致雪崩的發(fā)生不僅僅這一種,但是我們需要采取一定的措施,來保證不讓這個(gè)噩夢(mèng)發(fā)生。而hystrix-go就很好的提供了 熔斷和降級(jí)的措施。它的主要思想在于,設(shè)置一些閥值,比如較大并發(fā)數(shù)(當(dāng)并發(fā)數(shù)大于設(shè)置的并發(fā)數(shù),攔截),錯(cuò)誤率百分比(請(qǐng)求數(shù)量大于等于設(shè)置 的閥值,并且錯(cuò)誤率達(dá)到設(shè)置的百分比時(shí),觸發(fā)熔斷)以及熔斷嘗試恢復(fù)時(shí)間等 。

使用

hystrix-go 的使用非常簡(jiǎn)單,你可以調(diào)用它的Go 或者Do方法,只是Go 方法是異步的方式。而Do  方法是同步方式。我們從一個(gè)簡(jiǎn)單的例子開啟。

_ = hystrix.Do("wuqq", func() error {
        // talk to other services
        _, err := http.Get("https://www.baidu.com/")
        if err != nil {
            fmt.Println("get error:%v",err)
            return err        }
        return nil
    }, func(err error) error {
        fmt.Printf("handle  error:%v\n", err)
        return nil
    })

Do 函數(shù)需要三個(gè)參數(shù),第一個(gè)參數(shù)commmand 名稱,你可以把每個(gè)名稱當(dāng)成一個(gè)獨(dú)立當(dāng)服務(wù),第二個(gè)參數(shù)是處理正常的邏輯,比如http 調(diào)用服務(wù),返回參數(shù)是err。如果處理|調(diào)用失敗,那么就執(zhí)行第三個(gè)參數(shù)邏輯, 我們稱為保底操作。由于服務(wù)錯(cuò)誤率過高導(dǎo)致熔斷器開啟,那么之后的請(qǐng)求也直接回調(diào)此函數(shù)。

既然熔斷器是按照配置的規(guī)則而進(jìn)行是否開啟的操作,那么我們當(dāng)然可以設(shè)置我們想要的值。

hystrix.ConfigureCommand("wuqq", hystrix.CommandConfig{
        Timeout:                int(3 * time.Second),
        MaxConcurrentRequests:  10,
        SleepWindow:            5000,
        RequestVolumeThreshold: 10,
        ErrorPercentThreshold:  30,
    })
    _ = hystrix.Do("wuqq", func() error {
        // talk to other services
        _, err := http.Get("https://www.baidu.com/")
        if err != nil {
            fmt.Println("get error:%v",err)
            return err        }
        return nil
    }, func(err error) error {
        fmt.Printf("handle  error:%v\n", err)
        return nil
    })

稍微解釋一下上面配置的值含義:

  • Timeout: 執(zhí)行command 的超時(shí)時(shí)間。

  • MaxConcurrentRequests:command 的較大并發(fā)量 。

  • SleepWindow:當(dāng)熔斷器被打開后,SleepWindow 的時(shí)間就是控制過多久后去嘗試服務(wù)是否可用了。

  • RequestVolumeThreshold: 一個(gè)統(tǒng)計(jì)窗口10秒內(nèi)請(qǐng)求數(shù)量。達(dá)到這個(gè)請(qǐng)求數(shù)量后才去判斷是否要開啟熔斷

  • ErrorPercentThreshold:錯(cuò)誤百分比,請(qǐng)求數(shù)量大于等于RequestVolumeThreshold并且錯(cuò)誤率到達(dá)這個(gè)百分比后就會(huì)啟動(dòng)熔斷

當(dāng)然你不設(shè)置的話,那么自動(dòng)走的默認(rèn)值。
hystrix-go怎么用

我們?cè)賮砜匆粋€(gè)簡(jiǎn)單的例子:

package mainimport (
   "fmt"
 "github.com/afex/hystrix-go/hystrix" "net/http" "time")type Handle struct{}func (h *Handle) ServeHTTP(r http.ResponseWriter, request *http.Request) {
   h.Common(r, request)}func (h *Handle) Common(r http.ResponseWriter, request *http.Request) {
   hystrix.ConfigureCommand("mycommand", hystrix.CommandConfig{
      Timeout:                int(3 * time.Second),
      MaxConcurrentRequests:  10,
      SleepWindow:            5000,
      RequestVolumeThreshold: 20,
      ErrorPercentThreshold:  30,
   })
   msg := "success"

  _ = hystrix.Do("mycommand", func() error {
      _, err := http.Get("https://www.baidu.com")
      if err != nil {
         fmt.Printf("請(qǐng)求失敗:%v", err)
         return err  }
      return nil
  }, func(err error) error {
      fmt.Printf("handle  error:%v\n", err)
      msg = "error"
  return nil
  })
   r.Write([]byte(msg))}func main() {
   http.ListenAndServe(":8090", &Handle{})}

我們開啟了一個(gè)http 服務(wù),監(jiān)聽端口號(hào)8090,所有請(qǐng)求的處理邏輯都在  Common 方法中,在這個(gè)方法中,我們主要是發(fā)起一次http請(qǐng)求,請(qǐng)求成功響應(yīng)success,如果失敗,響應(yīng)失敗原因。

我們?cè)賹懥硪粋€(gè)簡(jiǎn)單程序,并發(fā)11 次的請(qǐng)求8090 端口。

package mainimport (
    "fmt"
    "io/ioutil"
    "net/http"
    "sync"
    "time")var client *http.Clientfunc init() {
    tr := &http.Transport{
        MaxIdleConns:    100,
        IdleConnTimeout: 1 * time.Second,
    }
    client = &http.Client{Transport: tr}}type info struct {
    Data interface{} `json:"data"`}func main() {
    var wg sync.WaitGroup    for i := 0; i < 11; i++ {
        wg.Add(1)
        go func(int2 int) {
            defer wg.Done()
            req, err := http.NewRequest("GET", "http://localhost:8090", nil)
            if err != nil {
                fmt.Printf("初始化http客戶端處錯(cuò)誤:%v", err)
                return
            }
            resp, err := client.Do(req)
            if err != nil {
                fmt.Printf("初始化http客戶端處錯(cuò)誤:%v", err)
                return
            }
            defer resp.Body.Close()
            nByte, err := ioutil.ReadAll(resp.Body)
            if err != nil {
                fmt.Printf("讀取http數(shù)據(jù)失敗:%v", err)
                return
            }
            fmt.Printf("接收到到值:%v\n", string(nByte))
        }(i)
    }
    wg.Wait()

    fmt.Printf("請(qǐng)求完畢\n")}

由于我們配置MaxConcurrentRequests 為10,那么意味著還有個(gè) g 請(qǐng)求會(huì)失敗:
hystrix-go怎么用
和我們想的一樣。

接著我們把網(wǎng)絡(luò)斷開,并發(fā)請(qǐng)求改成10次。再次運(yùn)行程序并發(fā)請(qǐng)求8090 端口,此時(shí)由于網(wǎng)絡(luò)已關(guān)閉,導(dǎo)致請(qǐng)求百度失?。?br/>hystrix-go怎么用
接著繼續(xù)請(qǐng)求:
hystrix-go怎么用
熔斷器已開啟,上面我們配置的RequestVolumeThresholdErrorPercentThreshold 生效。

然后我們把網(wǎng)連上,五秒后 (SleepWindow的值)繼續(xù)并發(fā)調(diào)用,當(dāng)前熔斷器處于半開的狀態(tài),此時(shí)請(qǐng)求允許調(diào)用依賴,如果成功則關(guān)閉,失敗則繼續(xù)開啟熔斷器。
hystrix-go怎么用
可以看到,有一個(gè)成功了,那么此時(shí)熔斷器已關(guān)閉,接下來繼續(xù)運(yùn)行函數(shù)并發(fā)調(diào)用:
hystrix-go怎么用
可以看到,10個(gè)都已經(jīng)是正常成功的狀態(tài)了。

那么問題來了,為什么最上面的圖只有一個(gè)是成功的?5秒已經(jīng)過了,并且當(dāng)前網(wǎng)絡(luò)正常,應(yīng)該是10個(gè)請(qǐng)求都成功,但是我們看到的只有一個(gè)是成功狀態(tài)。通過源碼我們可以找到答案:
具體邏輯在判斷當(dāng)前請(qǐng)求是否可以調(diào)用依賴

if !cmd.circuit.AllowRequest() {
            ......
            return
        }
func (circuit *CircuitBreaker) AllowRequest() bool {
    return !circuit.IsOpen() || circuit.allowSingleTest()}func (circuit *CircuitBreaker) allowSingleTest() bool {
    circuit.mutex.RLock()
    defer circuit.mutex.RUnlock()

    now := time.Now().UnixNano()
    openedOrLastTestedTime := atomic.LoadInt64(&circuit.openedOrLastTestedTime)
    if circuit.open && now > openedOrLastTestedTime+getSettings(circuit.Name).SleepWindow.Nanoseconds() {
    /
        swapped := atomic.CompareAndSwapInt64(&circuit.openedOrLastTestedTime, openedOrLastTestedTime, now) //這一句才是關(guān)鍵
        if swapped {
            log.Printf("hystrix-go: allowing single test to possibly close circuit %v", circuit.Name)
        }
        return swapped    }

    return false}

這段代碼首先判斷了熔斷器是否開啟,并且當(dāng)前時(shí)間大于 上一次開啟熔斷器的時(shí)間+SleepWindow 的時(shí)間,如果條件都符合的話,更新此熔斷器新的openedOrLastTestedTime ,是通過  CompareAndSwapInt64 原子操作完成的,意外著必然只會(huì)有一個(gè)成功。
此時(shí)熔斷器還是半開的狀態(tài),接著如果能拿到令牌,執(zhí)行run 函數(shù)(也就是Do傳入的第二個(gè)簡(jiǎn)單封裝后的函數(shù)),發(fā)起http 請(qǐng)求,如果成功,上報(bào)成功狀態(tài),關(guān)閉熔斷器。如果失敗,那么熔斷器依舊開啟。
hystrix-go怎么用

hystrix-go怎么用

看完了這篇文章,相信你對(duì)“hystrix-go怎么用”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

當(dāng)前標(biāo)題:hystrix-go怎么用-創(chuàng)新互聯(lián)
轉(zhuǎn)載源于:http://m.rwnh.cn/article10/dgsgdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、小程序開發(fā)、全網(wǎng)營銷推廣微信小程序Google、用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
沈丘县| 绩溪县| 长乐市| 临猗县| 宁夏| 平武县| 衡南县| 泗洪县| 蕲春县| 上饶县| 西城区| 仁化县| 大新县| 湄潭县| 卢湾区| 巴塘县| 黎平县| 博湖县| 襄垣县| 威宁| 大竹县| 乌拉特中旗| 浠水县| 土默特右旗| 亚东县| 格尔木市| 塘沽区| 拉萨市| 惠东县| 安顺市| 潮安县| 灵石县| 株洲县| 克什克腾旗| 铅山县| 平原县| 太原市| 汝南县| 呈贡县| 宝清县| 万安县|