真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

golang中怎么實(shí)現(xiàn)一個(gè)熔斷器

本篇文章給大家分享的是有關(guān)golang中怎么實(shí)現(xiàn)一個(gè)熔斷器,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

閻良網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),閻良網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為閻良超過千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的閻良做網(wǎng)站的公司定做!

對(duì)目前開源熔斷器的對(duì)比

熔斷器名稱hystrixgo-breaker
滑動(dòng)窗口計(jì)數(shù)支持不支持
限流支持不支持
阻塞讀
對(duì)半開啟的處理滑動(dòng)計(jì)數(shù)器+閾值連續(xù)成功則轉(zhuǎn)移到close
對(duì)監(jiān)控的支持支持metric采集不支持
降級(jí)處理支持hook支持hook
解決并發(fā)尖刺不支持支持
代碼結(jié)構(gòu)易讀性稍差較好

我們一一展開來講

計(jì)數(shù)模塊

計(jì)數(shù)模塊是熔斷器的核心,網(wǎng)上有針對(duì)計(jì)數(shù)器的大篇幅的分析針對(duì)這里引用知乎上一位大佬的比較類型的文章,根據(jù)最后的比較我們選擇滑動(dòng)窗口的算法來完成計(jì)數(shù)需求。 在hystrix的設(shè)計(jì)中,滑動(dòng)窗口的比較重要的是寫入時(shí)刻和讀取時(shí)刻,因?yàn)槲覀兒苋菀紫氲皆谶@兩個(gè)環(huán)節(jié)涉及到對(duì)一塊內(nèi)存并發(fā)讀寫的問題,首先我們不建議采用go-breaker的全加鎖(讀寫都加鎖)的設(shè)計(jì),因?yàn)殒i在發(fā)生競(jìng)爭(zhēng)時(shí)會(huì)掛起線程,從而降低了CPU的使用率和共享內(nèi)存總線上的同步通信量,那么我們參考hystrix,采用異步提交的方法,也就是將結(jié)果放入一個(gè)隊(duì)列中,不斷消費(fèi)這個(gè)隊(duì)列,這么做有幾點(diǎn)好處

消息串行化,減少寫入讀取數(shù)據(jù)不必要競(jìng)爭(zhēng)
在數(shù)據(jù)生產(chǎn)層--->數(shù)據(jù)存儲(chǔ)層中間構(gòu)造出中間層,方便進(jìn)行監(jiān)控統(tǒng)計(jì)收集等操作
方便控制消息的消費(fèi)情況

在實(shí)現(xiàn)上采用channel的數(shù)據(jù)結(jié)構(gòu),消費(fèi)有高效保證。但是事物都有兩面性,這種設(shè)計(jì)帶來的問題有

滑動(dòng)窗口統(tǒng)計(jì)需要訪問當(dāng)前窗口內(nèi)所有數(shù)據(jù)
串行化沒有將統(tǒng)計(jì)性能發(fā)揮最大(雖然在計(jì)數(shù)豐方面表現(xiàn)很快)
業(yè)務(wù)要允許流量尖刺的出現(xiàn)(假設(shè)沒有加限流)

其中2,3點(diǎn)經(jīng)過調(diào)研都在業(yè)務(wù)允許范圍內(nèi),且針對(duì)第三點(diǎn)我們可以增加限流策略來完善這一點(diǎn)。 golang中怎么實(shí)現(xiàn)一個(gè)熔斷器

限流

hystrix天生限流,所有請(qǐng)求先過令牌桶然后進(jìn)入熔斷統(tǒng)計(jì),go-breaker還沒有這方面支持,在限流這里我們懷疑要不要在一起做(畢竟熔斷是熔斷,限流是限流),所以做了另一個(gè)方案,在半開啟時(shí)進(jìn)行限流放行請(qǐng)求,這樣比較符合半開啟時(shí)的請(qǐng)求通過策略,同時(shí)進(jìn)行統(tǒng)計(jì),限流策略采用退化版本令牌桶,方法如下:

type limitPoolManager struct {
	max     int
	tickets chan *struct{}
	lock    *sync.RWMutex
}

/*
方法返回一個(gè)限流器
*/
func NewLimitPoolManager(max int) *limitPoolManager {
	lpm := new(limitPoolManager)
	tickets := make(chan *struct{}, max)
	for i := 0; i < max; i++ {
		tickets <- &struct{}{}
	}
	lpm.max = max
	lpm.tickets = tickets
	lpm.lock = &sync.RWMutex{}
	return lpm
}

/*
方法填充限流器所有令牌
*/
func (this *limitPoolManager) ReturnAll() {
	this.lock.Lock()
	defer this.lock.Unlock()
	if len(this.tickets) == 0 {
		for i := 0; i < this.max; i++ {
			this.tickets <- &struct{}{}
		}
	}
}

/*
方法返回一個(gè)令牌,得到令牌返回true,令牌用完后返回false
*/
func (this *limitPoolManager) GetTicket() bool {
	this.lock.RLock()
	defer this.lock.RUnlock()
	select {
	case <-this.tickets:
		return true
	default:
		return false
	}
}

/*
方法返回剩余令牌數(shù)
*/
func (this *limitPoolManager) GetRemaind() int {
	this.lock.RLock()
	defer this.lock.RUnlock()
	return len(this.tickets)
}

阻塞讀

因?yàn)榇谢O(shè)計(jì)所以在每次收失敗請(qǐng)求時(shí)可以對(duì)窗口內(nèi)數(shù)據(jù)進(jìn)行錯(cuò)誤率轉(zhuǎn)化。避免hystrix與go-breaker的鎖爭(zhēng)搶

半開啟處理

以上+本節(jié)主流程基本完結(jié),現(xiàn)梳理整個(gè)流程明確half-open時(shí)處理:

當(dāng)熔斷器為close時(shí)。只有當(dāng)出現(xiàn)錯(cuò)誤請(qǐng)求時(shí),才進(jìn)行錯(cuò)誤率統(tǒng)計(jì),統(tǒng)計(jì)過閾值則狀態(tài)轉(zhuǎn)移到open,正確請(qǐng)求則正常計(jì)數(shù)。
當(dāng)熔斷器為half-open時(shí),僅當(dāng)令牌桶中還有令牌時(shí)接收請(qǐng)求否則熔斷。令牌桶中還有令牌時(shí),出現(xiàn)錯(cuò)誤請(qǐng)求則更新熔斷休眠時(shí)間并返回所有令牌等待下次半開啟,正常請(qǐng)求則進(jìn)入半開啟時(shí)統(tǒng)計(jì)達(dá)到閾值則狀態(tài)轉(zhuǎn)移到close。
當(dāng)熔斷器為open時(shí),僅當(dāng)熔斷休眠時(shí)間小于當(dāng)前時(shí)間時(shí),當(dāng)熔斷器狀態(tài)轉(zhuǎn)移到half-open,可以進(jìn)行第二條,否則執(zhí)行熔斷

首先判斷是否是半開啟狀態(tài)

switch this.counter.GetStatus() {
	case STATE_OPEN:
		if this.cycleTime < time.Now().Local().Unix() {
			return OPEN_TO_HALF_ERROR
		}
		return BREAKER_OPEN_ERROR
	}

其次如果是半開啟狀態(tài)則取令牌,取到令牌則執(zhí)行請(qǐng)求,進(jìn)入熔斷時(shí)計(jì)數(shù),否則直接熔斷

/*取令牌*/
		if !this.lpm.GetTicket() {
			this.safelCalllback(fallback, BREAKER_OPEN_ERROR)
			return nil
		}
		/*執(zhí)行方法*/
		runErr := run()
		if runErr != nil {
			this.fail()
			this.safelCalllback(fallback, runErr)
			return runErr
		}
		this.success()
		return nil

流量尖刺處理

流量尖刺的削峰伴隨著限流的邏輯,所以可以在請(qǐng)求到達(dá)時(shí)優(yōu)先進(jìn)入令牌桶

監(jiān)控&降級(jí)

提供hook函數(shù),在限流或者執(zhí)行失敗時(shí)可以提供降級(jí)或者回掉

/*
執(zhí)行函數(shù)
*/
type runFunc func() error

/*
回調(diào)函數(shù)
*/
type fallbackFunc func(error)

/*
Do方法結(jié)合熔斷策略執(zhí)行run函數(shù)
其中參數(shù)包括:上下文ctx,策略名name,將要執(zhí)行方法run,以及回調(diào)函數(shù)fallback.其中ctx,name,run必傳
run函數(shù)的錯(cuò)誤會(huì)直接同步返回,回調(diào)函數(shù)fallback接收除了run錯(cuò)誤以外還會(huì)接收熔斷時(shí)錯(cuò)誤,調(diào)用方如果需要降級(jí)可在fallback中自己判斷
*/
func Do(ctx context.Context, name string, run runFunc, fallback fallbackFunc) error {
........
}

以上就是golang中怎么實(shí)現(xiàn)一個(gè)熔斷器,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


文章標(biāo)題:golang中怎么實(shí)現(xiàn)一個(gè)熔斷器
URL鏈接:http://weahome.cn/article/jhoidg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部