自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一言不合就重構(gòu)

開(kāi)發(fā) 架構(gòu)
本文從健康檢查的背景,原組件存在的問(wèn)題,以及我們的理想態(tài)出發(fā),調(diào)研了業(yè)界的方案,結(jié)合實(shí)際情況,選擇了適合的方案,并總結(jié)之前系統(tǒng)的問(wèn)題,設(shè)計(jì)一個(gè)更加合理的新系統(tǒng),從開(kāi)發(fā)閉環(huán)到上線。

hello,大家好呀,我是小樓。

前段時(shí)間不是在忙么,忙的內(nèi)容之一就是花了點(diǎn)時(shí)間重構(gòu)了一個(gè)服務(wù)的健康檢查組件,目前已經(jīng)慢慢在灰度上線,本文就來(lái)分享下這次重構(gòu)之旅,也算作個(gè)總結(jié)吧。

背景

服務(wù)健康檢查簡(jiǎn)介

服務(wù)健康檢查是應(yīng)對(duì)分布式應(yīng)用下某些服務(wù)節(jié)點(diǎn)不健康問(wèn)題的一種解法。如下圖,消費(fèi)者調(diào)用提供方集群,通常通過(guò)注冊(cè)中心獲取提供方的地址,根據(jù)負(fù)載均衡算法選取某臺(tái)具體機(jī)器發(fā)起調(diào)用。

圖片

假設(shè)某臺(tái)機(jī)器意外宕機(jī),服務(wù)消費(fèi)方不能感知,就會(huì)導(dǎo)致流量有損,如果此時(shí)有一種檢測(cè)服務(wù)節(jié)點(diǎn)健康狀態(tài)并及時(shí)剔除的機(jī)制,就能大大增加線上服務(wù)的穩(wěn)定性。

原服務(wù)健康檢查實(shí)現(xiàn)原理

我們是自研的注冊(cè)中心,健康檢查也算注冊(cè)中心的一部分,其原理很簡(jiǎn)單,可分為三個(gè)階段:

  • 從注冊(cè)中心獲取需要檢查的實(shí)例(即地址,由ip、port組成)
  • 對(duì)每個(gè)地址發(fā)起 TCP 建鏈請(qǐng)求,建鏈成功視為健康
  • 對(duì)判定為不健康的實(shí)例進(jìn)行摘除,對(duì)原不健康現(xiàn)在健康的實(shí)例進(jìn)行恢復(fù),摘除恢復(fù)通過(guò)調(diào)用注冊(cè)中心提供的接口實(shí)現(xiàn)

圖片

當(dāng)然這是大致流程,還有不少細(xì)節(jié),例如獲取探活實(shí)例時(shí)一些不需要探活的服務(wù)會(huì)被排除(如一些基礎(chǔ)服務(wù)如MySQL、Redis);為了防止網(wǎng)絡(luò)抖動(dòng)導(dǎo)致健康狀態(tài)判定有誤,會(huì)增加一些判定策略,如連續(xù) N 次建連失敗視為不健康;對(duì)不健康實(shí)例摘除時(shí)也計(jì)算了摘除閾值,如一個(gè)集群的機(jī)器都被判定為不健康,那也不能把它們?nèi)?,因?yàn)榇藭r(shí)全摘和不摘差別不大(請(qǐng)求都會(huì)報(bào)錯(cuò)),甚至全摘還要承擔(dān)風(fēng)險(xiǎn),考慮集群容量問(wèn)題,可以設(shè)個(gè)閾值,如最多只能摘三分之一的機(jī)器。

原服務(wù)健康檢查存在的問(wèn)題

1. 容量問(wèn)題

原組件是物理機(jī)時(shí)代的產(chǎn)物,當(dāng)時(shí)實(shí)例數(shù)量并不多,所以最初是單機(jī)設(shè)計(jì),只部署在一臺(tái)物理機(jī)上,隨著公司業(yè)務(wù)發(fā)展,實(shí)例數(shù)量增多,單機(jī)達(dá)到瓶頸,于是做了一次升級(jí),通過(guò)配置文件來(lái)指定每個(gè)節(jié)點(diǎn)的健康檢查任務(wù)分片。

圖片

2. 容災(zāi)問(wèn)題

單機(jī)就必然存在宕機(jī)風(fēng)險(xiǎn),即使檢查任務(wù)已經(jīng)做了分片,但是寫(xiě)在配置中,無(wú)法動(dòng)態(tài)調(diào)配,當(dāng)某個(gè)節(jié)點(diǎn)宕機(jī),則它負(fù)責(zé)的實(shí)例健康檢查就會(huì)失效。

3.部署效率問(wèn)題

部署在物理機(jī)且分片是寫(xiě)在配置中,無(wú)論是擴(kuò)容還是機(jī)器過(guò)保置換,都要修改配置,人為操作效率太低,而且容易出錯(cuò)。

4. 新需求支持效率問(wèn)題

隨著云原生時(shí)代的邁進(jìn),對(duì)健康檢查提出了一些新的需求,例如只探端口的聯(lián)通性可能不能代表服務(wù)的健康程度,甚至公司內(nèi)還有一些其他不在注冊(cè)中心上的服務(wù)也想復(fù)用這個(gè)健康檢查組件的能力,日益增長(zhǎng)的需求同原組件沉重的歷史包袱之間存在著不可調(diào)和的矛盾。

5. 迭代過(guò)程中的穩(wěn)定性問(wèn)題

原組件沒(méi)有灰度機(jī)制,開(kāi)發(fā)了新功能上線是一把梭,如果出問(wèn)題,就是個(gè)大故障,影響面非常廣。

需要解決這么多問(wèn)題,如果在原基礎(chǔ)上改,穩(wěn)定性和效率都非常令人頭疼,于是一個(gè)念頭油然而生:重構(gòu)!

技術(shù)方案調(diào)研

業(yè)界常見(jiàn)服務(wù)健康檢查方案

在設(shè)計(jì)新方案前,我們看看業(yè)界對(duì)于健康檢查都是怎么做的,從兩個(gè)角度展開(kāi)調(diào)研,注冊(cè)中心的健康檢查和非注冊(cè)中心的健康檢查

注冊(cè)中心健康檢查

方案

代表產(chǎn)品

優(yōu)點(diǎn)

缺點(diǎn)

SDK 心跳上報(bào)

Nacos 1.x 臨時(shí)實(shí)例


處理心跳消耗資源過(guò)多

SDK 長(zhǎng)連接 + 心跳保持

Nacox 2.x 臨時(shí)實(shí)例、SofaRegistry、Zookeeper

感知快

SDK 實(shí)現(xiàn)復(fù)雜

集中式主動(dòng)健康檢查

Nacos 永久實(shí)例

無(wú)需SDK參與,可實(shí)現(xiàn)語(yǔ)義探活

集中式壓力大時(shí),時(shí)延增大

非注冊(cè)中心健康檢查

K8S 健康檢查 — LivenessProbe

與集中式健康檢查做對(duì)比


LivenessProbe

原健康檢查組件

實(shí)現(xiàn)方式

k8s原生,分布式(sidecar模式)

自研,集中式

檢查發(fā)起者

kubelet,與業(yè)務(wù)容器在同一物理機(jī)

集中部署的服務(wù)

適用范圍

k8s容器(彈性云)

容器、物理機(jī)、虛擬機(jī)等

支持的檢查方式

tcp、http、exec、grpc

tcp、http

健康檢查基本配置

容器啟動(dòng)延時(shí)檢查時(shí)間、檢查間隔時(shí)間、檢查超時(shí)時(shí)間、最小連續(xù)成功數(shù)、最小連續(xù)失敗數(shù)

檢查超時(shí)時(shí)間、連續(xù)失敗次數(shù)、最大摘除比例

檢測(cè)不健康時(shí)動(dòng)作

殺死容器,容器再根據(jù)重啟策略決定是否重啟

從注冊(cè)中心上摘除

兜底

無(wú)

有,可配摘除比例

結(jié)合公司背景進(jìn)行選型

我們的大背景是技術(shù)棧不統(tǒng)一,編程語(yǔ)言有 Java、Go、PHP、C++等,基于成本考慮,我們更傾向瘦SDK的方案。

于是注冊(cè)中心常見(jiàn)的 SDK 長(zhǎng)連接+心跳保持方案被排除,SDK主動(dòng)上報(bào)心跳也不考慮。

而 K8S 的健康檢查方案僅僅使用于 K8S 體系,我們還有物理機(jī),而且 K8S 的 LivenessProbe 并不能做到開(kāi)箱即用,至少我們不想讓節(jié)點(diǎn)不健康時(shí)被殺死,兜底策略也需要重新開(kāi)發(fā)。

所以最終我們還是選擇了與原健康檢查組件相同的方案 — 集中式主動(dòng)健康檢查。

理想態(tài)

基于原健康檢查組件在使用中的種種問(wèn)題,我們總結(jié)出一個(gè)好的健康檢查組件該有的樣子:

  • 故障自動(dòng)轉(zhuǎn)移
  • 可水平擴(kuò)容
  • 快速支持豐富靈活的需求
  • 新需求迭代,本身的穩(wěn)定性需要有保障

設(shè)計(jì)開(kāi)發(fā)

總體設(shè)計(jì)

組件由四大模塊組成:

Dispatcher:負(fù)責(zé)從數(shù)據(jù)源獲取數(shù)據(jù),生成并派發(fā)任務(wù)

Prober:負(fù)責(zé)健康檢查任務(wù)的執(zhí)行

Decider:根據(jù)健康檢查結(jié)果決策是否需要變更健康狀態(tài)

Performer:根據(jù)決策結(jié)果執(zhí)行相應(yīng)動(dòng)作

各模塊對(duì)外暴露接口,隱藏內(nèi)部實(shí)現(xiàn)。數(shù)據(jù)源面向接口編程,可替換。

服務(wù)發(fā)現(xiàn)模型

在詳細(xì)介紹各個(gè)模塊的設(shè)計(jì)之前,先簡(jiǎn)單介紹一下我們的服務(wù)發(fā)現(xiàn)模型,有助于后續(xù)的表述和理解。

一個(gè)服務(wù)名在公司內(nèi)是唯一的,調(diào)用時(shí)需指定服務(wù)名,獲取對(duì)應(yīng)的地址。

一個(gè)服務(wù)又可以包含多個(gè)集群,集群可以是物理上的隔離集群,也可以是邏輯上的隔離集群,集群下再包含地址。

圖片

協(xié)程模型設(shè)計(jì)

編程語(yǔ)言我們選擇的是 Go,原因有二:第一是健康檢查這種 IO 密集型任務(wù)與 Go 的協(xié)程調(diào)度比較契合,開(kāi)發(fā)速度,資源占用都還可以;第二是我們組一直用 Go,經(jīng)驗(yàn)豐富,所以語(yǔ)言選擇我們沒(méi)有太多的考慮。

但在協(xié)程模型的設(shè)計(jì)上,我們做了一些思考。

數(shù)據(jù)源的獲取,由于服務(wù)、集群信息不經(jīng)常變化,所以緩存在內(nèi)存中,每分鐘進(jìn)行一次同步,地址數(shù)據(jù)需要實(shí)時(shí)拉取。

Dispatcher 先獲取所有的服務(wù),然后根據(jù)服務(wù)獲取集群,到這里都是在一個(gè)協(xié)程內(nèi)完成,接下來(lái)獲取地址有網(wǎng)絡(luò)開(kāi)銷,所以開(kāi) N 個(gè)協(xié)程,每個(gè)協(xié)程負(fù)責(zé)一部分集群地址,每個(gè)地址都生成一個(gè)單獨(dú)的任務(wù),派發(fā)給 Prober。

Prober 負(fù)責(zé)健康檢查,完全是 IO 操作,內(nèi)部用一個(gè)隊(duì)列存放派發(fā)來(lái)的任務(wù),然后開(kāi)很多協(xié)程從隊(duì)列中取任務(wù)去做健康檢查,檢查完成后將結(jié)果交給 Decider 做決策。

Decider 決策時(shí)比較重要的是需要算出是否會(huì)被兜底,這里有兩點(diǎn)需要考慮:

一是最初獲取的實(shí)例狀態(tài)可能不是最新了,需要重新獲取一次;

二是對(duì)于同一個(gè)集群不能并發(fā)地去決策,決策應(yīng)該串行才不會(huì)導(dǎo)致決策混亂,舉個(gè)反例,如果一個(gè)集群3臺(tái)機(jī)器,最多摘除1臺(tái),如果2臺(tái)同時(shí)掛掉,并發(fā)決策時(shí),2個(gè)協(xié)程各自以為能摘,最后結(jié)果是摘除了2臺(tái),和預(yù)期只摘1臺(tái)不符。這個(gè)如何解決?我們最后搞了 N 個(gè)隊(duì)列存放健康檢查結(jié)果,按服務(wù)+集群的哈希值路由到隊(duì)列,保證每個(gè)集群的檢測(cè)結(jié)果都路由到同一個(gè)隊(duì)列,再開(kāi) N 個(gè)協(xié)程,每個(gè)協(xié)程消費(fèi)一個(gè)隊(duì)列,這樣就做到了順序執(zhí)行。

決策之后的動(dòng)作執(zhí)行就是調(diào)用更新接口,所以直接共用決策的協(xié)程。用一張大圖來(lái)總結(jié):

圖片

水平擴(kuò)容 & 故障自動(dòng)轉(zhuǎn)移

水平擴(kuò)容與故障自動(dòng)轉(zhuǎn)移只要能做到動(dòng)態(tài)地?cái)?shù)據(jù)分片即可,每個(gè)健康檢查組件在啟動(dòng)時(shí)將自己注冊(cè)到一個(gè)中心的協(xié)調(diào)器(可以是 etcd),并且監(jiān)聽(tīng)其他節(jié)點(diǎn)的在線狀態(tài),派發(fā)任務(wù)時(shí),按服務(wù)名哈希,判斷該任務(wù)是否應(yīng)該由自己調(diào)度,是則執(zhí)行,否則丟棄。

圖片

當(dāng)某個(gè)節(jié)點(diǎn)掛掉或者擴(kuò)容時(shí),其他節(jié)點(diǎn)都能感知到當(dāng)前集群的變化,自動(dòng)進(jìn)行數(shù)據(jù)分片的重新劃分。

小流量機(jī)制

小流量的實(shí)現(xiàn)采取部署兩個(gè)集群的方式,一個(gè)正常集群,一個(gè)小流量集群,小流量集群負(fù)責(zé)部分不重要的服務(wù),作為灰度,正常集群負(fù)責(zé)其他服務(wù)的健康檢查任務(wù)。

只需要共享一個(gè)小流量的配置即可,我們按組織、服務(wù)、集群、環(huán)境等維度去設(shè)計(jì)這個(gè)配置,基本可以任意粒度配置。

圖片

可擴(kuò)展性

可擴(kuò)展性也是設(shè)計(jì)里非常重要的一環(huán),可從數(shù)據(jù)源、檢查方式擴(kuò)展、過(guò)濾器等方面稍微談一談。

數(shù)據(jù)源可插拔

面向接口編程,我們將數(shù)據(jù)源抽象為讀數(shù)據(jù)源與寫(xiě)數(shù)據(jù)源,只要符合這兩個(gè)接口的數(shù)據(jù)源,就能無(wú)縫對(duì)接。

檢查方式易擴(kuò)展

健康檢查其實(shí)就是給定一個(gè)地址,再加一堆配置去進(jìn)行檢查,至于怎么檢查可以自己實(shí)現(xiàn),目前已實(shí)現(xiàn)的有TCP、HTTP方式,未來(lái)還可能會(huì)實(shí)現(xiàn)諸如Dubbo、gRPC、thrift等語(yǔ)義級(jí)別的檢查方式。

過(guò)濾器

在派發(fā)任務(wù)時(shí),有一個(gè)可能會(huì)隨時(shí)修改的邏輯是過(guò)濾掉一些不需要檢查的服務(wù)、集群、實(shí)例,這塊用責(zé)任鏈的模式就能很好地實(shí)現(xiàn),后期想增刪就只需要插拔鏈中的一環(huán)即可。

可擴(kuò)展性是代碼層面的內(nèi)容,所以這里只列舉了部分比較典型的例子。

灰度上線

由于我們是重寫(xiě)了一個(gè)組件來(lái)代替原組件,需要平滑地替換舊系統(tǒng),為此我們做了2方面的工作:

設(shè)計(jì)了一個(gè)可按組織、服務(wù)、集群、環(huán)境等維度的降級(jí)開(kāi)關(guān),降級(jí)分為3檔,不降級(jí)、半降級(jí)、全降級(jí)。不降級(jí)很好理解,就是啥正常工作,全降級(jí)是雖然檢查,但是不摘除也不恢復(fù),相當(dāng)于空跑,半降級(jí)是只恢復(fù)健康但不摘除。試想如果健康檢查在上線過(guò)程中,誤摘除,此時(shí)降級(jí),豈不是無(wú)法恢復(fù)健康?所以我們讓它保留恢復(fù)能力。

我們利用上述的小流量設(shè)計(jì)來(lái)逐步將服務(wù)遷移到新組件上來(lái),灰度的服務(wù)新組件負(fù)責(zé),非灰度的服務(wù)老組件負(fù)責(zé),等全部灰度完成,停掉老組件,新組件的灰度集群再切換為正常集群。

踩坑調(diào)優(yōu)

在灰度過(guò)程中,我們發(fā)現(xiàn)了一個(gè)問(wèn)題,有的集群機(jī)器非常多,超過(guò)了1000臺(tái),而我們的決策是順序執(zhí)行,而且決策有時(shí)還會(huì)去實(shí)時(shí)查詢實(shí)例狀態(tài),假設(shè)平均每次決策10ms,1000臺(tái)順序決策完也得10s,我們期望每輪的檢測(cè)要在3秒左右完成,光這一個(gè)集群就得10秒,顯然不能接受。

為了我們做了第一次的優(yōu)化:

我們當(dāng)時(shí)在線上環(huán)境測(cè)試,一個(gè)集群有2000多臺(tái)機(jī)器,但大部分機(jī)器是禁用的狀態(tài),也就是這部分機(jī)器其實(shí)做健康檢查是個(gè)無(wú)用功,禁用的機(jī)器,無(wú)論是否健康都不會(huì)被消費(fèi),所以我們的第一個(gè)優(yōu)化便是在派發(fā)任務(wù)時(shí)過(guò)濾掉禁用的機(jī)器,這樣就解決了線下環(huán)境的問(wèn)題。

但我們上到生產(chǎn)環(huán)境時(shí)仍然發(fā)現(xiàn)決策很慢,線上一個(gè)集群只有少量的機(jī)器被禁用,第一次的優(yōu)化基本就沒(méi)什么效果了,而且線上機(jī)器數(shù)量可能更多,任務(wù)堆積會(huì)很嚴(yán)重,我們發(fā)現(xiàn)其他的隊(duì)列可能比較空閑,只有大集群所在的隊(duì)列很忙。

所以我們進(jìn)行了第二次優(yōu)化:

從業(yè)務(wù)視角出發(fā),其實(shí)需要順序決策的只有不健康的實(shí)例,對(duì)于健康的實(shí)例決策時(shí)不需要考慮兜底,所以我們將按檢查結(jié)果進(jìn)行分類,健康的檢查結(jié)果隨機(jī)派發(fā)到任意隊(duì)列處理,不健康的檢查結(jié)果嚴(yán)格按服務(wù)+集群路由到特定隊(duì)列處理,這樣既保證了兜底決策時(shí)的順序,也解決了隊(duì)列負(fù)載不均衡的狀況。

總結(jié)

本文從健康檢查的背景,原組件存在的問(wèn)題,以及我們的理想態(tài)出發(fā),調(diào)研了業(yè)界的方案,結(jié)合實(shí)際情況,選擇了適合的方案,并總結(jié)之前系統(tǒng)的問(wèn)題,設(shè)計(jì)一個(gè)更加合理的新系統(tǒng),從開(kāi)發(fā)閉環(huán)到上線。

我覺(jué)得系統(tǒng)設(shè)計(jì)是一個(gè)取舍的過(guò)程,別人的方案不見(jiàn)得是最優(yōu)的,適合的才是最好的,而且有時(shí)并不是純技術(shù)解決問(wèn)題,可能從業(yè)務(wù)角度去思考,可能更加豁然開(kāi)朗。

責(zé)任編輯:武曉燕 來(lái)源: 捉蟲(chóng)大師
相關(guān)推薦

2022-09-02 09:14:10

監(jiān)控系統(tǒng)

2018-10-09 12:02:05

筆記本

2025-01-06 12:31:18

2017-01-11 08:45:31

編程開(kāi)發(fā)ETL

2022-05-17 13:40:44

居家辦公蘋(píng)果微軟

2016-10-28 13:14:25

2016-11-02 15:47:12

盈高科技準(zhǔn)入控制

2024-10-28 12:54:36

2018-11-07 19:46:30

本地ERP

2024-09-04 15:44:52

2025-02-13 10:37:36

2023-07-13 15:10:06

2022-08-31 08:14:46

算法key鏈表

2017-05-05 14:12:31

互聯(lián)網(wǎng)

2020-05-25 09:45:47

開(kāi)發(fā)技能代碼

2023-03-29 15:28:35

百度文心一言

2023-02-08 07:14:51

文心一言ChatGPT機(jī)器人

2023-12-28 15:09:58

文心一言百度飛槳

2023-03-24 12:55:13

文心一言百度模型

2023-03-17 07:25:16

李彥宏百度文心一言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)