成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

微服務(wù)注冊(cè)中心注冊(cè)表與hashcode實(shí)現(xiàn)golang版

KitorinZero / 1184人閱讀

摘要:背景基于負(fù)載均衡的服務(wù)調(diào)用基于負(fù)載均衡的服務(wù)相互調(diào)用指的是通過基于等負(fù)載均衡軟件來構(gòu)建一個(gè)負(fù)載均衡服務(wù),所有的服務(wù)調(diào)用都通過負(fù)載均衡器從負(fù)載均衡的這種模式下其實(shí)有兩個(gè)主要的問題一是中心化,整個(gè)系統(tǒng)都基于負(fù)載均衡器,負(fù)載均衡就相當(dāng)于整個(gè)業(yè)

背景 基于負(fù)載均衡的服務(wù)調(diào)用

基于負(fù)載均衡的服務(wù)相互調(diào)用指的是通過基于Lvs、Haproxy、Nginx等負(fù)載均衡軟件來構(gòu)建一個(gè)負(fù)載均衡服務(wù),所有的服務(wù)調(diào)用都通過負(fù)載均衡器

從負(fù)載均衡的這種模式下其實(shí)有兩個(gè)主要的問題: 一是中心化,整個(gè)系統(tǒng)都基于負(fù)載均衡器,負(fù)載均衡就相當(dāng)于整個(gè)業(yè)務(wù)的中心,雖然我們可以通過一些高可用手段來保證,但其實(shí)內(nèi)部流量通常是巨大的,很容易出現(xiàn)性能瓶頸 二是增加了一次TCP交互

當(dāng)然也有很多好處,比如可以做一些負(fù)載均衡、長(zhǎng)鏈接維護(hù)、分布式跟蹤等,這不是本文重點(diǎn)

基于注冊(cè)中心的服務(wù)調(diào)用

所有的服務(wù)都啟動(dòng)后都通過注冊(cè)中心來注冊(cè)自己,同時(shí)把注冊(cè)中心里面的服務(wù)信息拉回本地,后續(xù)調(diào)用,就直接檢查本地的服務(wù)和節(jié)點(diǎn)信息來進(jìn)行服務(wù)節(jié)點(diǎn)的調(diào)用

注冊(cè)中心中的注冊(cè)表

每個(gè)服務(wù)節(jié)點(diǎn)都會(huì)來注冊(cè)中心進(jìn)行服務(wù)注冊(cè),那數(shù)據(jù)如何在服務(wù)端進(jìn)行保存呢,其實(shí)就是注冊(cè)表,其實(shí)等同于windows 里面的注冊(cè)表,每個(gè)服務(wù)都來注冊(cè),把自己的信息上報(bào)上來,然后注冊(cè)中心吧注冊(cè)表,返回給client端,那服務(wù)之間就知道要調(diào)用服務(wù)的節(jié)點(diǎn)啦

注冊(cè)中心事件隊(duì)列

微服務(wù)注冊(cè)注冊(cè)中心通常會(huì)大量的服務(wù)注冊(cè), 那不能每次客戶端來請(qǐng)求的時(shí)候,服務(wù)端都返回全量的數(shù)據(jù),在數(shù)據(jù)傳輸?shù)脑O(shè)計(jì)中,通常會(huì)有一種增量同步,其實(shí)在注冊(cè)中心中也類似 注冊(cè)中心通過將最近的服務(wù)變更事件保存在一個(gè)事件隊(duì)列中,后續(xù)每次客戶端拉取只返回增量數(shù)據(jù),這樣服務(wù)端的忘了壓力就會(huì)小很多

注冊(cè)中心hashcode

增量數(shù)據(jù)有一個(gè)問題就是,如果客戶端錯(cuò)過啦某些事件,比如事件隊(duì)列滿了,則客戶端與注冊(cè)中心的注冊(cè)表就會(huì)不一致, 所以eureka里面引入了一個(gè)hashcode的概念,通過比對(duì)hashcode是否相同, 如果不同則客戶端需要重新全量拉取

代碼實(shí)現(xiàn) 系統(tǒng)架構(gòu)

系統(tǒng)整體上分為兩個(gè)端:客戶端(Client)和注冊(cè)中心(Server) Server: 提供服務(wù)注冊(cè)和獲取注冊(cè)表的接口, 同時(shí)本地把保存服務(wù)和節(jié)點(diǎn)的對(duì)應(yīng)信息,變更事件寫入eventQueue Client: 調(diào)用server接口進(jìn)行服務(wù)注冊(cè), 同時(shí)調(diào)用注冊(cè)表拉取接口進(jìn)行注冊(cè)表拉取,保存懂啊LocalRegistry

應(yīng)用與節(jié)點(diǎn)信息

Server端的服務(wù)注冊(cè)表里面的服務(wù)和節(jié)點(diǎn)的信息,我通過Application和lease來維護(hù) Application: 代表一個(gè)應(yīng)用,里面會(huì)包含服務(wù)對(duì)應(yīng)的節(jié)點(diǎn)信息 Lease: 維護(hù)一個(gè)節(jié)點(diǎn)的信息,比如心跳信息

服務(wù)端注冊(cè)表 注冊(cè)表結(jié)構(gòu)體

服務(wù)端注冊(cè)表結(jié)構(gòu)體Registry主要包含三部分信息: lock(讀寫鎖)、apps(應(yīng)用對(duì)應(yīng)信息)、eventQueue(事件隊(duì)列) Lock: 注冊(cè)中心是典型的讀多寫少的應(yīng)用,server端注冊(cè)表可能同時(shí)提供給N個(gè)服務(wù)進(jìn)行讀取,所以這里采用讀寫鎖 apps: 保存應(yīng)用對(duì)應(yīng)的信息, 其實(shí)后面寫完發(fā)現(xiàn),沒必要使用,只使用基礎(chǔ)的map就可以搞定 eventQueue: 每次注冊(cè)表變更都寫入事件到里面

// Registry 注冊(cè)表
type Registry struct {
	lock       sync.RWMutex
	apps       sync.Map
	duration   time.Duration
	eventQueue *EventQueue
}
注冊(cè)表服務(wù)注冊(cè)

注冊(cè)流程主要分為下面幾部分:

    從注冊(cè)表獲取對(duì)應(yīng)的應(yīng)用Application

    調(diào)用Application的add接口添加節(jié)點(diǎn)

    為節(jié)點(diǎn)創(chuàng)建一個(gè)Lease

    保存節(jié)點(diǎn)信息到Application.Node里

    將事件寫入到eventQueue

// Registr 注冊(cè)服務(wù)
func (r *Registry) Registr(name, node string) bool {
	r.lock.Lock()
	defer r.lock.Unlock()
	app := r.getApp(name)
	if app == nil {
		app = NewApplication(name)
		r.apps.Store(name, app)
	}

	if lease, ok := app.add(node, r.duration); ok {
		r.eventQueue.Push(&Event{lease: lease, action: ADD})
		return true
	}
	return false
}
注冊(cè)表拉取

全量拉取通過all接口拉取全量的返回的是服務(wù)對(duì)應(yīng)的節(jié)點(diǎn)切片 增量拉取通過details接口返回增量的變更事件和服務(wù)端注冊(cè)表的hashcode

// all 全量拉取
func (r *Registry) all() map[string][]string {
	r.lock.RLock()
	defer r.lock.RUnlock()
	apps := make(map[string][]string)
	r.apps.Range(func(k, v interface{}) bool {
		name, app := k.(string), v.(*Application)
		nodes := []string{}
		for key := range app.Node {
			nodes = append(nodes, key)
		}
		apps[name] = nodes
		return true
	})
	return apps
}
// details 增量拉取
func (r *Registry) details() []*Event {
	r.lock.RLock()
	defer r.lock.RUnlock()
	events := []*Event{}
	for {
		event := r.eventQueue.Pop()
		if event == nil {
			break
		}
		events = append(events, event)
	}
	return events
}
hashcode

hashcode是一個(gè)一致性的保證,eureka里面主要是通過拼接所有的服務(wù)名稱和節(jié)點(diǎn)的個(gè)數(shù)來生成的一個(gè)字符串,這里我們也采用這種方式,

func (r *Registry) hashCode() string {
	r.lock.RLock()
	defer r.lock.RUnlock()
	hashCodes := []string{}
	r.apps.Range(func(_, value interface{}) bool {
		app := value.(*Application)
		hashCodes = append(hashCodes, app.HashCode())
		return true
	})
	sort.Sort(sort.StringSlice(hashCodes))
	return strings.Join(hashCodes, "|")
}
客戶端注冊(cè)表 數(shù)據(jù)結(jié)構(gòu)

客戶端本地注冊(cè)表其實(shí)就比較簡(jiǎn)單了,只需要存儲(chǔ)服務(wù)和節(jié)點(diǎn)的對(duì)應(yīng)信息即可

// LocalRegistry 本地注冊(cè)表
type LocalRegistry struct {
	lock sync.RWMutex
	apps map[string][]string
}
客戶端邏輯架構(gòu)

啟動(dòng)流程: 啟動(dòng)時(shí)客戶端首先調(diào)用注冊(cè)接口進(jìn)行自我注冊(cè),然后調(diào)用poll拉取全量注冊(cè)表

func (c *Client) start() {
	c.wg.Add(1)
	c.registr()
	c.poll()
	go c.loop()
}

主循環(huán)

func (c *Client) loop() {
	timer := time.NewTimer(time.Second)
	for {
            // 從服務(wù)的拉取增量事件,details內(nèi)部會(huì)直接應(yīng)用,然后返回服務(wù)端返回的注冊(cè)表的hashcode
		respHashCode := c.details()
		localHashCode := c.registry.hashCode()

            // 如果發(fā)現(xiàn)本地和服務(wù)的的注冊(cè)表的hashcode不同,則全量拉取
		if respHashCode != localHashCode {
			fmt.Printf("client app %s node %s poll hashcode: %s
", c.App, c.Name, respHashCode)
			c.poll()
		}
		select {
		case <-timer.C:
			timer.Reset(time.Second)
		case <-c.done:
			c.wg.Done()
			return
		}
	}
}
驗(yàn)證邏輯
func main() {
        // 生成服務(wù)端
	server := NewServer("aliyun", time.Second)

        // 注冊(cè)兩個(gè)test服務(wù)的節(jié)點(diǎn)
	clientOne := NewClient("test", "1.1.1.1:9090", server)
	clientOne.start()
	clientTwo := NewClient("test", "1.1.1.2:9090", server)
	clientTwo.start()

    // 注冊(cè)兩個(gè)hello服務(wù)的節(jié)點(diǎn)
	clientThree := NewClient("hello", "1.1.1.3:9090", server)
	clientThree.start()
	clientFour := NewClient("hello", "1.1.1.4:9090", server)
	clientFour.start()

	time.Sleep(time.Second * 3)
        // 驗(yàn)證每個(gè)服務(wù)節(jié)點(diǎn)的注冊(cè)表的hashcode是否一致
	println(clientOne.details())
	println(clientTwo.details())
	println(clientThree.details())
	println(clientFour.details())
	println(clientTwo.details() == clientOne.details())
	println(clientThree.details() == clientFour.details())
	println(clientOne.details() == clientFour.details())

	clientOne.stop()
	clientTwo.stop()
	clientThree.stop()
	clientFour.stop()
}

通過結(jié)果我們可以看出,節(jié)點(diǎn)增量拉取了注冊(cè)表,同時(shí)如果發(fā)現(xiàn)與本地的hashcode不同就進(jìn)行全量拉取,并最終達(dá)成一致

lr event add 1.1.1.3:9090 hello
lr event add 1.1.1.4:9090 hello
lr event add client app hello node 1.1.1.4:9090 poll hashcode: hello_2|test_2
1.1.1.1:9090 test
lr event add 1.1.1.2:9090 test
client app test node 1.1.1.1:9090 poll hashcode: hello_2|test_2
client app test node 1.1.1.2:9090 poll hashcode: hello_2|test_2
client app hello node 1.1.1.3:9090 poll hashcode: hello_2|test_2
hello_2|test_2
hello_2|test_2
hello_2|test_2
hello_2|test_2
true
true
true
總結(jié)

微服務(wù)注冊(cè)中心注冊(cè)表的這種實(shí)現(xiàn)機(jī)制,到這基本上就明白了,注冊(cè)中心 通過增量、全量、hashcode三種機(jī)制來保證客戶端與注冊(cè)中心的注冊(cè)表的同步

其實(shí)一個(gè)工業(yè)級(jí)的注冊(cè)中心還是很麻煩的,比如注冊(cè)表中那個(gè)事件隊(duì)列,我現(xiàn)在的實(shí)現(xiàn)只有一個(gè)節(jié)點(diǎn)能獲取增量,其他的都會(huì)通過hashcode來觸發(fā)全量拉取,后續(xù)文章里面會(huì)相信介紹下,這塊緩存和定時(shí)器來實(shí)現(xiàn)增量數(shù)據(jù)的打包

其實(shí)在go里面大家注冊(cè)中心都是基于etcd、consul直接watch去做的,基本上可以完成eureka服務(wù)的8/9十的功能,但是當(dāng)需要與公司現(xiàn)有的java做集成,可能就需要eureaka這種注冊(cè)中心了

未完待續(xù) 關(guān)注公共號(hào): 布衣碼農(nóng)

更多精彩內(nèi)容可以查看www.sreguide.com

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/7194.html

相關(guān)文章

  • Dubbo服務(wù)消費(fèi)者調(diào)用過程

    摘要:先來說第種類型,即遠(yuǎn)程通信的,看的源碼,調(diào)用過程大致內(nèi)容就是將通過遠(yuǎn)程通信將信息傳遞給服務(wù)器端,服務(wù)器端接收到該信息后,找到對(duì)應(yīng)的本地,然后通過反射執(zhí)行相應(yīng)的方法,將方法的返回值再通過遠(yuǎn)程通信將結(jié)果傳遞給客戶端。 showImg(https://segmentfault.com/img/remote/1460000015285374?w=640&h=363); 上圖是服務(wù)消費(fèi)的主過程:...

    B0B0 評(píng)論0 收藏0
  • 從零到百億互聯(lián)網(wǎng)金融架構(gòu)發(fā)展史

    摘要:總體介紹在互聯(lián)網(wǎng)金融行業(yè)一百多億其實(shí)也算不上大平臺(tái),也就是二級(jí)陣營(yíng)吧,其實(shí)每次的架構(gòu)升級(jí)都是隨著業(yè)務(wù)重大推進(jìn)而伴隨的,在前一代系統(tǒng)架構(gòu)上遇到的問題,業(yè)務(wù)開發(fā)過程中積累一些優(yōu)秀的開發(fā)案例,在下一代系統(tǒng)開發(fā)中就會(huì)大力推進(jìn)架構(gòu)升級(jí)。 回想起從公司成立敲出的第一行代碼算起到現(xiàn)在也快三年了,平臺(tái)的技術(shù)架構(gòu),技術(shù)體系也算是經(jīng)歷了四次比較重大的升級(jí)轉(zhuǎn)化(目前第四代架構(gòu)體系正在進(jìn)行中),臨近年底也想抽...

    mrcode 評(píng)論0 收藏0
  • 從零到百億互聯(lián)網(wǎng)金融架構(gòu)發(fā)展史

    摘要:總體介紹在互聯(lián)網(wǎng)金融行業(yè)一百多億其實(shí)也算不上大平臺(tái),也就是二級(jí)陣營(yíng)吧,其實(shí)每次的架構(gòu)升級(jí)都是隨著業(yè)務(wù)重大推進(jìn)而伴隨的,在前一代系統(tǒng)架構(gòu)上遇到的問題,業(yè)務(wù)開發(fā)過程中積累一些優(yōu)秀的開發(fā)案例,在下一代系統(tǒng)開發(fā)中就會(huì)大力推進(jìn)架構(gòu)升級(jí)。 回想起從公司成立敲出的第一行代碼算起到現(xiàn)在也快三年了,平臺(tái)的技術(shù)架構(gòu),技術(shù)體系也算是經(jīng)歷了四次比較重大的升級(jí)轉(zhuǎn)化(目前第四代架構(gòu)體系正在進(jìn)行中),臨近年底也想抽...

    U2FsdGVkX1x 評(píng)論0 收藏0
  • 明星分分合合的洪荒點(diǎn)擊量,博Mesh服務(wù)化改造如何支撐?(附PPT下載)

    摘要:為了解決這一系列問題,微博從年開發(fā)了語言的框架,并基于此完成了服務(wù)化改造。這些經(jīng)歷之下微博也積累了一套服務(wù)治理型的服務(wù)化體系。的版,所要解決的是微博平臺(tái)內(nèi)部服務(wù)之間的調(diào)用,因此協(xié)議時(shí),其實(shí)并沒有考慮到跨語言的問題,用的是對(duì)比較友好的。 showImg(https://segmentfault.com/img/remote/1460000012601596?w=1080&h=606); ...

    ShowerSun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<