日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

有赞统一接入层架构演进

發(fā)布時(shí)間:2024/4/11 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 有赞统一接入层架构演进 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文系云原生應(yīng)用最佳實(shí)踐杭州站活動(dòng)演講稿整理。杭州站活動(dòng)邀請了 Apache APISIX 項(xiàng)目 VP 溫銘、又拍云平臺開發(fā)部高級工程師莫紅波、螞蟻金服技術(shù)專家王發(fā)康、有贊中間件開發(fā)工程師張超,分享云原生落地應(yīng)用的經(jīng)驗(yàn)心得,以下是張超《有贊統(tǒng)一接入層架構(gòu)演進(jìn)》分享內(nèi)容。

張超,有贊中間件團(tuán)隊(duì)開發(fā)工程師,網(wǎng)關(guān)、Service Mesh 領(lǐng)域的專家,熱衷技術(shù),對 Golang、Nginx、Ruby 語言等有深入的研究。

大家好,我是來自有贊的張超,有贊中間件團(tuán)隊(duì)的開發(fā)工程師。今天給大家?guī)碛匈澖尤雽蛹軜?gòu)演進(jìn)的分享。

先簡單給大家介紹下有贊接入層,內(nèi)部名為 YZ7,從概念來講它與網(wǎng)關(guān)比較接近,是基于 OpenResty 和 Nginx 來實(shí)現(xiàn)的,主要是有標(biāo)準(zhǔn) C 模塊,自研發(fā)的 Nginx C 模塊,以及基于 lua 實(shí)現(xiàn)的模塊。它作為有贊業(yè)務(wù)流量的公網(wǎng)入口,提供 Traffic Shaping,包括限流、安全相關(guān)的像 WAF、請求路由等功能,請求路由包含標(biāo)準(zhǔn)的藍(lán)綠發(fā)布、灰色發(fā)布功能,負(fù)載均衡等方面的功能。今天的分享,主要是從下面從三個(gè)方面來深入解析:

  • 舊版接入層架構(gòu)痛點(diǎn)

  • 新架構(gòu)設(shè)計(jì)分析

  • 新架構(gòu)設(shè)計(jì)總結(jié)

舊版接入層架構(gòu)痛點(diǎn)

首先從舊版接入層架構(gòu)的相關(guān)痛點(diǎn)出發(fā),開始新架構(gòu)的設(shè)計(jì)分析。

上圖是舊版接入層架構(gòu)的縱向切面,方案是早幾年之前的。當(dāng)時(shí)流行用 redis 做配置同步,它天然的主從同步協(xié)議確實(shí)非常適合。其中黃色箭頭線是配置同步,數(shù)據(jù)從 redis master 同步到每個(gè)實(shí)例上的 redis slave,然后本級的 YZ7 會去輪巡本級的 redis,并把數(shù)據(jù)讀到自身內(nèi)存中。

為什么有右下方的 k8ssync controller 呢?因?yàn)榍皫啄?K8S 逐漸的成為熱門,很多應(yīng)用都開始走向容器化的道路。

YZ7 是基于 OpenResty 來開發(fā)的,整個(gè)技術(shù)棧都是基于 lua,在 K8S 的生態(tài)里 lua 并不在其中。如果想要 watch K8S 里面的服務(wù),需要實(shí)時(shí)知道它有哪些 endpoints。雖然通過 lua 也可以實(shí)現(xiàn),但是需要重頭做一個(gè)類似像 K8S 標(biāo)準(zhǔn)的 client-go 庫,這就得不償失了。因此會應(yīng)用一個(gè)使用 GoLang 編寫的 k8sssync controller,它負(fù)責(zé)向 K8S 獲取它所感興趣的后端服務(wù) endpoints 數(shù)據(jù),再通過 YZ7 配置的 API,再次寫入到 redis master,最后由 redis master 分發(fā)到每個(gè) YZ7 的實(shí)例上。

舊版接入層架構(gòu)的缺點(diǎn)

  • redis master 的單點(diǎn)問題:沒有使用 redis closter 或者哨兵方案,只是簡單的主從模式,出現(xiàn)問題時(shí)會導(dǎo)致配置無法下發(fā)。

  • 當(dāng)接入層是按照多機(jī)房的規(guī)模進(jìn)行部署的,因?yàn)?redis master 是一個(gè)單點(diǎn),它必然存在于一個(gè)機(jī)房中,從它所在的機(jī)房將數(shù)據(jù)同步到其他機(jī)房的 redis slave 時(shí),容易受到機(jī)房之間專線穩(wěn)定性的影響,穩(wěn)定性差,配置同步的延時(shí)就高。

  • 當(dāng) redis master 出現(xiàn)問題,這意味著從 k8ssync controller 同步過來的 K8S 內(nèi)部服務(wù) endpoints 數(shù)據(jù)無法實(shí)時(shí)同步到 YZ7 實(shí)例上。如果一些服務(wù)實(shí)例的 point 被清除了,接入層不能第一時(shí)間感知到。如此一來當(dāng)請求進(jìn)來,這邊還在用已經(jīng)下線的 point IP,導(dǎo)致請求會 502、504,引起服務(wù)不可用。還有一個(gè)缺點(diǎn),因歷史原因?qū)е碌?k8ssync controller 也是單點(diǎn),如果它掛了,K8S server 會無法同步,同樣會導(dǎo)致服務(wù)不可用,甚至引起大規(guī)模的故障。

  • 配置不具備屬性特征。無法在配置層面做多樣化處理,包括配置的灰度下發(fā)。配置的灰度下發(fā)這個(gè)詞是我個(gè)人提出來的,先保留這個(gè)疑問,后面會詳細(xì)地揭開。

新架構(gòu)設(shè)計(jì)三大組件

帶著舊版接入層的種種缺陷,接下來需要設(shè)計(jì)出能夠解決這些缺陷的新架構(gòu)。當(dāng)然,在設(shè)計(jì)新架構(gòu)時(shí)需要遵循一些架構(gòu)相關(guān)的要點(diǎn)。

  • 首先就是解決基礎(chǔ)的單點(diǎn)問題,為服務(wù)可用性提供保障。

  • 組件的設(shè)計(jì)需要是無狀態(tài),可灰度、可回滾、可觀測的。

  • 無狀態(tài):意味著服務(wù)可以有彈性的進(jìn)行擴(kuò)縮容,應(yīng)對彈性流量時(shí)非常的有幫助。

  • 可灰度:服務(wù)某個(gè)組件的更新,它的影響面不能是整個(gè)集群或者是所有的流量,必須有可灰度的能力,只影響部分流量與部分實(shí)例。

  • 可回滾:當(dāng)服務(wù)更新發(fā)布后,出現(xiàn)一些連環(huán)的反映,可以單獨(dú)的對它回滾。

  • 可觀測:從各個(gè)角度來增強(qiáng)組件的可觀測性,包括日志、logging、metrics 甚至是 opentracing 等相關(guān)功能要做的更好,能最大地把控到組件在線上的運(yùn)行程度。

  • 降低組件間的耦合程度。各組件職能獨(dú)立,可獨(dú)立測試部署。即使架構(gòu)設(shè)計(jì)的再好,但是部署復(fù)雜,測試麻煩,就會加大成本。

遵循上述要點(diǎn)后,新架構(gòu)方案細(xì)看有點(diǎn)像 Service Mesh 控制面、數(shù)據(jù)面分離和 APISIX 的控制面、數(shù)據(jù)面分離。中間虛線以上是控制面,下方則是數(shù)據(jù)面。控制面的核心組件叫 YZ7-manager,左邊對接 K8S,右邊對接 ETCD,ETCD 是它的配置存儲中心,所有接入層的配置會存放在 ETCD 中,同時(shí)又會去 watch K8S。

虛線下方的數(shù)據(jù)面是每個(gè) YZ7 的實(shí)例,每個(gè)實(shí)例上都有一個(gè)伴生進(jìn)程,叫做 YZ7-agent,agent 會做一些雜活。YZ7 則是保留核心功能的網(wǎng)關(guān),從下往上的紅線箭頭即是請求的方向。

控制面核心組件 manager

  • manager 是一個(gè)配置提供者,類似于 Istio Pilot,Istio 1.5 版本之前是由多個(gè)組件組成,其中最重要的就是 Pilot。配置保存在 ETCD 中,ETCD 的特點(diǎn)就是穩(wěn)定可靠,所以選型用了 ETCD。

  • manager 是無狀態(tài)的,可以做到水平擴(kuò)容。

  • manager 接管了原來 k8ssync controller 的功能,由它去 watch K8S,代替了原 K8S-think 的功能。因?yàn)?manager 是無狀態(tài)、可水平擴(kuò)容的,解決了 YZ7 K8S-think 的單點(diǎn)問題。同時(shí)在原架構(gòu)當(dāng)中,YZ7 配置的 admin server 和現(xiàn)在的 APISIX 是非常相似的,它的 admin server 是和網(wǎng)關(guān)放在一起的,而在新架構(gòu)中把網(wǎng)關(guān) admin server 替掉,只放在控制面的 YZ7-manager 中。

  • 最后一個(gè)核心功能就是配置下發(fā)功能,從 YZ7-manager 的控制面,把數(shù)據(jù)下發(fā)到每個(gè)數(shù)據(jù)面。

控制面核心組件 agent

數(shù)據(jù)面的核心組件是 agent,是一個(gè)伴生服務(wù),與每一個(gè)接入層的實(shí)例綁定。核心功能就是負(fù)責(zé)配置同步,包括配置注解的釋義,這個(gè)和配置層面的灰度是相關(guān)的。還有配置間依賴管理,當(dāng)有 A、B 兩種配置時(shí),可能 A 配置是依賴于 B 配置的,相當(dāng)于 APISIX 里的 route 和 upstream。agent 的服務(wù)會把配置間的依賴管理做好。

接入層 YZ7

我們把原有配置的 admin server 去掉了,同時(shí)負(fù)責(zé)向 redis 獲取數(shù)據(jù)的部分配置相關(guān)代碼也去掉了,只留下了 http 接口。我們可以從外部將配置推送到 YZ7 實(shí)例中,保持在共享內(nèi)存中。原來的網(wǎng)關(guān)功能全部保留,沒有做很多的改造,僅保留核心功能,簡化了組件。

新架構(gòu)設(shè)計(jì)細(xì)節(jié)要點(diǎn)

講完三個(gè)核心組件之后,再來聊一下新架構(gòu)中幾個(gè)比較重要的細(xì)節(jié)。

第一:從控制面的 YZ7-manager,到數(shù)據(jù)面的 YZ7-agent,配置下發(fā)協(xié)議怎么設(shè)計(jì)才能高效可靠?

第二:從 YZ7-agent 和 YZ7 之間,數(shù)據(jù)是用推模式還是拉模式?

第三:配置注解怎么實(shí)現(xiàn)?

第四:配置依賴怎么保證?

帶著這四個(gè)問題,接下來會詳細(xì)講解,逐個(gè)擊破:

控制面 YZ7-manager 到 數(shù)據(jù)面 YZ7-agent

首先,我們對于協(xié)議的要求一定是簡單、可靠的,否則理解成本高,開發(fā)成本也會提高。

其次,協(xié)議必須支持服務(wù)端的主動(dòng)推送,就像 APISIX 的配置生效時(shí)間很低,因?yàn)?ETCD 是支持 watch 功能。而 Kong 的配置時(shí)間相對比較高,是因?yàn)?kong 上對接的是 PostgreSQL 和 Cassandra,這兩種關(guān)系數(shù)據(jù)庫是不支持 watch 的。服務(wù)端有數(shù)據(jù)變更,客戶端只能通過輪巡的方式獲取。輪巡的間隔太長,配置生效時(shí)間就高;間隔太短,可以及時(shí)獲取到數(shù)據(jù)變更,但是資源消耗會更高。

基于上述兩點(diǎn),我們以 gRPC 為基礎(chǔ),并參考 xDS,設(shè)計(jì)了一個(gè)新的協(xié)議。初次連接時(shí),可以全量獲取控制面的數(shù)據(jù),后續(xù)一直保持長連接,可以增量地獲取服務(wù)端的數(shù)據(jù)配置變更。

上圖是 gRPC、XDS 的片段。最上面有一個(gè)ConfigDiscoverService,這個(gè) gRPC 就是做配置同步的核心,其中核心的兩個(gè) message 是 configrequest 與 configresponse。

configrequest 中,node 是帶有某個(gè)數(shù)據(jù)鏈實(shí)例相關(guān)的數(shù)據(jù),比如所在的集群,hostname,IP 等。resourcecondition 是在數(shù)據(jù)面聲明感興趣的配置,比如對路由配置,對 upstream 配置或?qū)缬蚺渲酶信d趣。在列表中把感興趣的配置全部聲明好,告訴服務(wù)端,控制面才能精準(zhǔn)的把所感興趣的配置推送到數(shù)據(jù)面。

configresponse 就是把響應(yīng)碼,包括 error detail 在出錯(cuò)的情況下,將包括錯(cuò)誤碼在內(nèi)的信息,把 resource 全部放在 resource 列表里面然后推送給客戶端。它的傳輸模型也比較簡單,客戶端會在連完之后發(fā)送 config request,然后服務(wù)端第一次會把所有的配置數(shù)據(jù)推送到客戶端。

當(dāng)一個(gè)接入層只是推送一些配置,它的配置量不會很大,幾百兆就非常多了,因此全量的推送并不會帶來特別多的帶寬與內(nèi)存上的開銷,全量推送也是一個(gè)低頻事件,不用過于擔(dān)憂它的性能。

隨著時(shí)間的推移,服務(wù)端會有新的配置變更,比如運(yùn)維新增了配置或是發(fā)布業(yè)務(wù)應(yīng)用,發(fā)布之后 pond 做了遷移,導(dǎo)致 pond 的endpoints 變更了??刂泼娓兄竭@些變更,會將這些數(shù)據(jù)實(shí)時(shí)地推送到 Client 端,完成控制面到數(shù)據(jù)面的配置推送。

這跟 xDS 協(xié)議是很相似的,xDS 里的 discovery request 發(fā)送到服務(wù)端之后,如果有數(shù)據(jù)就把數(shù)據(jù)推回來,在discover response,如果沒有數(shù)據(jù)會其中加入一個(gè) none 標(biāo)志,告訴我們準(zhǔn)備同步這個(gè) discovery quest。沒有數(shù)據(jù)時(shí)相當(dāng)于是請求 ACQ 的功能。我們設(shè)計(jì)的有點(diǎn)類似 xDS 的簡化版本,沒有這方面的功能。

數(shù)據(jù)面 YZ7-agent 到 接入層 YZ7

從 YZ7-agent 到 YZ7 即數(shù)據(jù)面的 agent 到數(shù)據(jù)面的實(shí)例,其配置同步的抉擇究竟是拉還是推?

首先來考慮拉,它的優(yōu)點(diǎn)是按需加載,在需要時(shí)去加載對應(yīng)的配置。缺點(diǎn)是如果配置提供方?jīng)]有像 ECTD 的 watch 功能,就需要數(shù)據(jù)存在內(nèi)存中必須要有淘汰的機(jī)制,否則就沒有辦法獲取到同一個(gè)實(shí)例新的配置變更。而如果配置使用了淘汰策略,帶來的問題就是配置生效時(shí)間高。生效時(shí)間高,對于一些靜態(tài)配置像路由、host service 配置是無關(guān)痛癢,但是對于容器化業(yè)務(wù)的 endpoints 變更,它需要盡可能快的推送數(shù)據(jù)面,否則可能會出現(xiàn) 502、504 等 5XX 的錯(cuò)誤。因此拉的模式不適用于新的架構(gòu)中。

其次是推模式,YZ7-agent 需要主動(dòng)把數(shù)據(jù)推到 YZ7。優(yōu)點(diǎn)是 YZ7 只需要做簡單的保存動(dòng)作即可,不需要考慮數(shù)據(jù)過期,而且組合的耦合程度會更低。這樣的 YZ7 交付給測試,可以加幾個(gè)接口,把需要用的測試數(shù)據(jù)推進(jìn)去就行,而不需要額外部署 YZ7-agent,對交付測試比較有利。缺點(diǎn)是依賴于別人推會有一個(gè)問題,如果服務(wù)是剛剛起來或者 Nginx 剛剛完成熱更新時(shí),共享內(nèi)存里是沒有數(shù)據(jù)的,要采用推模式就必須解決這個(gè)問題。我們采用的方式是 agent 會定期的把數(shù)據(jù)緩存轉(zhuǎn)儲到磁盤上,當(dāng)接入層 YZ7 實(shí)例熱更新完或剛啟動(dòng)的時(shí)候,就會從磁盤上加載舊的數(shù)據(jù),保證可以正常起來。再者是強(qiáng)制在此時(shí)要求 YZ7-agent 全量推送一次數(shù)據(jù),就可以立刻達(dá)到最新的配置。

配置注解的實(shí)現(xiàn)

設(shè)計(jì)配置注解是為了做配置灰度。其作用是當(dāng)新增了配置,但不希望對集群里所有的實(shí)例生效,只需要集群中的一兩個(gè)小規(guī)模實(shí)例生效時(shí)方便進(jìn)行驗(yàn)證。因?yàn)槿绻渲糜姓`可能會帶來大規(guī)模故障,而進(jìn)行配置灰度可以有效降低故障的影響面。

上圖是配置 payload 的片段,從上往下接入的是配置數(shù)據(jù),里面只有一個(gè) server,而 antotations 就是這個(gè)注解,里面的 canary 字段可以設(shè)計(jì)成灰度配置所需字段。這是按照 hostsname 來配置,這個(gè)配置只有 hosts2 或者 hosts3 才會生效。其中的 id、name、kind 是用來給配置做標(biāo)識的,像 name、種類、UUID 之類的。其實(shí) K8S 的聲明配置也是如此的,具體的配置是放在 steak 面,外面會有像 laybol 等云數(shù)據(jù)相關(guān)的,圖中的 antotations 就是效仿 K8S 聲明式配置的 antotations。

有贊是一個(gè) SaaS 服務(wù)提供者,域名非常多,配置非常復(fù)雜,比較依賴人為配置。為了降低因人為操作失誤引起的故障面,需要有配置灰度這樣的功能。操作流程也很簡單,首先運(yùn)維平臺上創(chuàng)建一個(gè)配置,并標(biāo)注為灰度配置,底層會創(chuàng)建出相關(guān)的配置注解。之后觀察配置在相關(guān)實(shí)例上的表現(xiàn),表現(xiàn)OK,就可以將該配置生效到所有的機(jī)器,去掉灰度配置注解,這時(shí)全部的接入層實(shí)例上也就生效了。如果出現(xiàn)問題,立刻刪除灰度配置,也可避免引起其他激烈的反應(yīng)。

創(chuàng)建灰度配置,并攜帶灰度注解。通過 YZ7-manager 分發(fā)到每個(gè) agent。agent 會判斷該配置在機(jī)器上是 hit 還是 miss。如果是 miss 就會忽略掉這個(gè)配置,不會推過去。如果是 hit 就推送到本機(jī)中的 YZ7。

當(dāng)灰度了一段時(shí)間,表現(xiàn)也正常,需要將其全部生效時(shí)就可以修改配置了,去掉灰度注解推送到 YZ7-manager 后會原封不動(dòng)的再推到 YZ7 各個(gè)實(shí)例上。左下角這臺是應(yīng)用了灰度配置,由于 name 是相同的,這時(shí)穩(wěn)定版本的配置就會把之前灰度版本的配置替換掉,所有接入層實(shí)例的配置也就都相同了。

當(dāng)發(fā)現(xiàn)配置有問題,刪除也會很簡單。配置刪除后,因?yàn)樽笙陆沁@臺已經(jīng)灰度命中了,它會把刪除配置的事件推到 YZ7,進(jìn)而 YZ7 會主動(dòng)刪除內(nèi)存中的副本。而左中、左下原本就沒有命中灰度配置,會直接忽略,到此這三臺YZ7的實(shí)例配置又恢復(fù)到了灰度配置應(yīng)用之前的狀態(tài)。

配置依賴管理

部分的配置間會有互相引用的關(guān)系。比如 host 配置,每一個(gè) host 可配置一個(gè)標(biāo)準(zhǔn)的錯(cuò)誤頁,錯(cuò)誤頁又是一個(gè)單獨(dú)的配置,在做 host 配置時(shí),就必須先有錯(cuò)誤頁配置,否則會沒辦法下發(fā)。所以數(shù)據(jù)面的 agent 就需要保證好數(shù)據(jù)配置的推送關(guān)系,當(dāng) A 配置依賴于 B 配置,就不能先把 A 配置推送到接入層實(shí)例。因?yàn)?A 配置和 B 配置中間推送有時(shí)間窗口,會無法正確處理在 A、B 時(shí)間窗口之間進(jìn)來的請求。

架構(gòu)設(shè)計(jì)總結(jié)

走向云原生,需要我們在工作中學(xué)習(xí)更多的借鑒在云原生方面好的組件,像 K8S、Envoy 等都是值得學(xué)習(xí)的優(yōu)秀范本。有贊接入層新架構(gòu)遵循的控制面和數(shù)據(jù)面的職能分離設(shè)計(jì)原則,就是參考了 Service Mesh 的設(shè)計(jì);配置下發(fā)協(xié)議是參考了 Envoy、xDS;加入注解的功能,設(shè)計(jì)上是參考了 K8S 的聲明式配置的聲明定義。

走向云原生的道路上我們應(yīng)該多向前看,把云原生上所需要的功能、學(xué)到的新東西更好的融入到工作當(dāng)中,把用到的組件能夠更好的契合到云原生當(dāng)中,走向云原生就會更有意義。

總結(jié)

以上是生活随笔為你收集整理的有赞统一接入层架构演进的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。