<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          利用etcd選舉sdk實(shí)踐master/slave故障轉(zhuǎn)移

          共 1146字,需瀏覽 3分鐘

           ·

          2022-04-23 00:20

          本次記錄[利用etcd選主sdk實(shí)踐master/slave故障轉(zhuǎn)移], 并利用etcdctl客戶端驗(yàn)證選主sdk的工作原理。

          master/slave高可用集群

          本文目標(biāo)

          在異地多機(jī)房部署節(jié)點(diǎn),slave作為備用實(shí)例啟動(dòng),但不接受業(yè)務(wù)流量, 監(jiān)測(cè)到master宕機(jī),slave節(jié)點(diǎn)自動(dòng)提升為master并接管業(yè)務(wù)流量。

          基本思路

          各節(jié)點(diǎn)向etcd注冊(cè)帶租約的節(jié)點(diǎn)信息, 并各自維持心跳保活,選主sdk根據(jù)目前存活的、最早創(chuàng)建的節(jié)點(diǎn)信息鍵值對(duì)?來(lái)確立leader,?并通過(guò)watch機(jī)制通知業(yè)務(wù)代碼leader變更。

          講道理,每個(gè)節(jié)點(diǎn)只需要知道兩個(gè)信息就能各司其職

          • ??誰(shuí)是leader ==> 當(dāng)前節(jié)點(diǎn)是什么角色===> 當(dāng)前節(jié)點(diǎn)該做什么事情

          • ??感知集群leader變更的能力 ===》當(dāng)前節(jié)點(diǎn)現(xiàn)在要不要改變行為

          除了官方etcd客戶端go.etcd.io/etcd/client/v3, 還依賴go.etcd.io/etcd/client/v3/concurrency?package:實(shí)現(xiàn)了基于etcd的分布式鎖、屏障、選舉

          選主過(guò)程實(shí)質(zhì)api
          競(jìng)選前先查詢leader了解現(xiàn)場(chǎng)查詢當(dāng)前存活的,最早創(chuàng)建的kv值*concurrency.Election.Leader()
          初始化時(shí),各節(jié)點(diǎn)向etcd阻塞式競(jìng)選各節(jié)點(diǎn)向etcd注冊(cè)帶租約的鍵值對(duì)*concurrency.Election.compaign
          建立master/slave集群,還能及時(shí)收到變更通知通過(guò)chan傳遞最新的leader value*concurrency.Election.Observe()


          重點(diǎn)解讀

          1.初始化etcd go客戶端

          注意:etcd客戶端和服務(wù)端是通過(guò)grpc來(lái)通信,目前新版本的etcd客戶端默認(rèn)使用非阻塞式連接, 也就是說(shuō)v3.New函數(shù)僅表示從指定配置創(chuàng)建etcd客戶端。

          為快速確定etcd選舉的可用性,本實(shí)踐使用阻塞式創(chuàng)建客戶端:

          cli,?err?:=?v3.New(v3.Config{
          ??Endpoints:???addr,
          ??DialTimeout:?time.Second?*?5,
          ??DialOptions:?[]grpc.DialOption{grpc.WithBlock()},
          ?})
          ?if?err?!=?nil?{
          ??log.WithField("instance",?Id).Errorln(err)
          ??return?nil,?err
          ?}

          2. 競(jìng)選

          使用阻塞式命令compaign競(jìng)選之前,應(yīng)先查詢當(dāng)前l(fā)eader:

          //?將id:ip:port作為競(jìng)選時(shí)寫入etcd的value
          func?(c?*Client)?Election(id?string,?notify?chan<-?bool)?error?{
          ?//競(jìng)選前先試圖去了解情況
          ?ctx,?cancel?:=?context.WithTimeout(context.Background(),?time.Second*3)
          ?defer?cancel()
          ?resp,?err?:=?c.election.Leader(ctx)
          ?if?err?!=?nil?{
          ??if?err?!=?concurrency.ErrElectionNoLeader?{
          ???return?err
          ??}
          ?}?else?{?//?已經(jīng)有l(wèi)eader了
          ??c.Leader?=?string(resp.Kvs[0].Value)
          ??notify?<-?(c.Leader?==?id)
          ?}

          ?if?err?=?c.election.Campaign(context.TODO(),?id);?err?!=?nil?{
          ??log.WithError(err).WithField("id",?id).Error("Campaign?error")
          ??return?err
          ?}?else?{
          ??log.Infoln("Campaign?success!!!")
          ??c.Leader?=?id
          ??notify?<-?true
          ?}
          ?c.election.Key()
          ?return?nil
          }

          參選:將持續(xù)刷新的leaseID作為key,將特定的客戶端標(biāo)記(這里使用ip:port)作為value,寫到etcd.

          當(dāng)選:當(dāng)前存活的、最早創(chuàng)建的key是leader?,?也就是說(shuō)leader故障轉(zhuǎn)移并不是隨機(jī)的

          3. watch leader變更

          golang使用信道完成goroutine通信,

          本例聲明信道:?notify = make(chan bool, 1)

          一石二鳥(niǎo):監(jiān)聽(tīng)該信道能夠知道集群leader是否發(fā)生變化;信道內(nèi)傳的值表示當(dāng)前節(jié)點(diǎn)是否是leader

          func?(c?*Client)?Watchloop(id?string,?notify?chan<-?bool)?error?{
          ?ch?:=?c.election.Observe(context.TODO())?//?觀察leader變更
          ?tick?:=?time.NewTicker(c.askTime)

          ?defer?tick.Stop()
          ?for?{
          ??var?leader?string

          ??select?{
          ??case?_?=?<-c.sessionCh:
          ???log.Warning("Recv?session?event")
          ???return?fmt.Errorf("session?Done")?//?一次續(xù)約不穩(wěn),立馬退出程序
          ??case?e?:=?<-ch:
          ???log.WithField("event",?e).Info("watch?leader?event")
          ???leader?=?string(e.Kvs[0].Value)
          ???ctx,?cancel?:=?context.WithTimeout(context.Background(),?time.Second*3)
          ???defer?cancel()
          ???resp,?err?:=?c.election.Leader(ctx)
          ???if?err?!=?nil?{
          ????if?err?!=?concurrency.ErrElectionNoLeader?{
          ?????return?err
          ????}?else?{?//?目前沒(méi)leader,開(kāi)始競(jìng)選了
          ?????if?err?=?c.election.Campaign(context.TODO(),?id);?err?!=?nil?{
          ??????log.WithError(err).WithField("id",?id).Error("Campaign?error")
          ??????return?err
          ?????}?else?{?//?競(jìng)選成功
          ??????leader?=?id
          ?????}
          ????}
          ???}?else?{
          ????leader?=?string(resp.Kvs[0].Value)
          ???}
          ??}
          ??if?leader?!=?c.Leader?{
          ???log.WithField("before",?c.Leader).WithField("after",?leader?==?id).Info("leader?changed")
          ???notify?<-?(leader?==?id)
          ??}
          ??c.Leader?=?leader
          ?}
          }

          c.election.Observe(context.TODO()) 返回最新的leader信息,配合select case控制結(jié)構(gòu)能夠及時(shí)拿到leader變更信息。

          如題:通過(guò)Leader字段和chan <- bool信道, 掌控了整個(gè)選舉集群的狀態(tài), 可根據(jù)這兩個(gè)信息去完成業(yè)務(wù)上的master/slave故障轉(zhuǎn)移。


          使用etcdctl確定leader

          election.Leader的源碼證明了[當(dāng)前存活的,最早創(chuàng)建的kv為leader]

          //?Leader?returns?the?leader?value?for?the?current?election.
          func?(e?*Election)?Leader(ctx?context.Context)?(*v3.GetResponse,?error)?{
          ?client?:=?e.session.Client()
          ?resp,?err?:=?client.Get(ctx,?e.keyPrefix,?v3.WithFirstCreate()...)
          ?if?err?!=?nil?{
          ??return?nil,?err
          ?}?else?if?len(resp.Kvs)?==?0?{
          ??//?no?leader?currently?elected
          ??return?nil,?ErrElectionNoLeader
          ?}
          ?return?resp,?nil
          }

          等價(jià)于

          ./etcdctl get /merc --prefix --sort-by=CREATE --order=ASCEND --limit=1

          --?sort-by?:以某標(biāo)準(zhǔn)(創(chuàng)建時(shí)間)檢索數(shù)據(jù)
          -- order :以升/降序給已檢出的數(shù)據(jù)排序
          -- limit:從以檢出的數(shù)據(jù)中取x條數(shù)據(jù)顯示

          有態(tài)度的馬甲建立了真?高質(zhì)量交流群:大佬匯聚、無(wú)事靜默、有事激活、深度思考。

          [長(zhǎng)按圖片加我好友]


          年終總結(jié):2021技術(shù)文大盤點(diǎn) ?| ?打包過(guò)去,面向未來(lái)

          項(xiàng)目總結(jié):麻雀雖小,五臟俱全

          理念總結(jié):實(shí)話實(shí)說(shuō):只會(huì).NET,會(huì)讓我們一直處于鄙視鏈、食物鏈的下游

          云原生系列:?什么是云原生?


          點(diǎn)“戳“在看

          體現(xiàn)態(tài)度很有必要!


          瀏覽 78
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91在线无精精品秘 白丝 | 亚洲视频无码 | 日韩无码电影 | 国内精品视频在线 | 成人毛片18毛片女人 |