多点生活在 Service Mesh 上的实践
陳鵬
金融級分布式架構(gòu)(antfin-sofa)
讀完需要
20
分鐘速讀僅需 5 分鐘
Service Mesh Webinar 是由 ServiceMesher 社區(qū)和 CNCF 聯(lián)合發(fā)起的線上直播活動(dòng),活動(dòng)將不定期舉行,為大家?guī)?Service Mesh 領(lǐng)域的知識和實(shí)踐分享。
本文根據(jù)5月28日晚 Service Mesh Webinar#1 多點(diǎn)生活平臺架構(gòu)組研發(fā)工程師陳鵬,線上主題分享《多點(diǎn)生活在 Service Mesh 上的實(shí)踐 -- Istio + MOSN?在 Dubbo場景下的探索之路》整理,文末包含本次分享的視頻回顧鏈接以及 PPT 下載地址。
前言
隨著多點(diǎn)生活的業(yè)務(wù)發(fā)展,傳統(tǒng)微服務(wù)架構(gòu)的面臨升級困難的問題。在云原生的環(huán)境下,Service Mesh 能給我們帶來什么好處。如何使用社區(qū)解決方案兼容現(xiàn)有業(yè)務(wù)場景,落地成符合自己的 Service Mesh 成為一個(gè)難點(diǎn)。
今天主要給大家分享一下 Service Mesh 的一些技術(shù)點(diǎn)以及多點(diǎn)生活在 Service Mesh 落地過程中適配 Dubbo 的一些探索。
首先我們從三個(gè)方面入手:
為什么需要 Service Mesh 改造;
探索 Istio 技術(shù)點(diǎn);
Dubbo 場景下的改造;
為什么需要 Service Mesh 改造
說到為什么需要改造,應(yīng)該先說一下 Service Mesh 和傳統(tǒng)微服務(wù)架構(gòu)的一些特點(diǎn)。
微服務(wù)
微服務(wù)一般有這些模塊:
安全;
配置中心;
調(diào)用鏈監(jiān)控;
網(wǎng)關(guān);
監(jiān)控告警;
注冊和發(fā)現(xiàn);
容錯(cuò)和限流;
這些模塊在傳統(tǒng)的微服務(wù)架構(gòu)中有的是和 SDK 結(jié)合在一起,有的是一個(gè)獨(dú)立的中間件。
特點(diǎn):
獨(dú)立部署;
模塊的邊界;
技術(shù)多樣性;
正是由于技術(shù)多樣性,微服務(wù)系統(tǒng)可以使用不同的語言進(jìn)行開發(fā),比如一個(gè)商城系統(tǒng),訂單系統(tǒng)使用 Java 開發(fā),庫存系統(tǒng)使用 Go 開發(fā),支付系統(tǒng)使用 Python 開發(fā),微服務(wù)之間通過輕量級通信機(jī)制協(xié)作,比如:HTTP/GRPC 等。比如目前多點(diǎn)使用的 Dubbo(服務(wù)治理框架),隨著多點(diǎn)生活的業(yè)務(wù)發(fā)展,目前遇到最棘手的問題就是中間件在升級過程中,推進(jìn)很慢,需要業(yè)務(wù)方進(jìn)行配合,接下來我們看看 Service Mesh。
Service Mesh
優(yōu)點(diǎn):
統(tǒng)一的服務(wù)治理;
服務(wù)治理和業(yè)務(wù)邏輯解耦;
缺點(diǎn):
增加運(yùn)維復(fù)雜度;
增加延時(shí);
需要更多技術(shù)棧;
看了 Service Mesh 的優(yōu)缺點(diǎn),如果我們 Mesh 化了之后就可以解決我們目前的痛點(diǎn),升級中間件只需要重新發(fā)布一下 Sidecar 就好了,不同語言開發(fā)的微服務(wù)系統(tǒng)可以采用同樣的服務(wù)治理邏輯,業(yè)務(wù)方就可以嘗試更多的技術(shù)。
探究 Istio 技術(shù)點(diǎn)
在談 Dubbo 場景下的改造之前我們先介紹一下 Istio 相關(guān)的技術(shù)點(diǎn),然后結(jié)合 Dubbo 場景應(yīng)該如何進(jìn)行適配。
MCP
MCP(Mesh Configuration Protocol)提供了一套用于訂閱(Watch)、推送(Push)的 API,分為 Source 和 Sink 兩個(gè)角色。
Source 是資源提供方(server),資源變化了之后推送給訂閱者(Pilot),Istio 1.5 之前這個(gè)角色就是 Galley 或者自定義 MCP Server;
Sink 是資源的訂閱者(client),在 Istio 1.5 之前這個(gè)角色就是 Pilot 和 Mixer,都是訂閱 Galley 或者自定義 MCP Server 的資源;
MCP 的訂閱、推送流程圖:
為了和實(shí)際情況結(jié)合,我們就以 MCPServer 作為 Source,Pilot 作為 Sink 來介紹訂閱、推送流程,其中 MCP 通信過程中所傳輸?shù)摹纲Y源」就是 Istio 定義的 CRD 資源,如:VirtualService、DestinationRules 等。
訂閱
Pilot 啟動(dòng)后會(huì)讀取 Configmap 的內(nèi)容,里面有一個(gè)?configSources?的一個(gè)數(shù)組配置(Istio 1.5 之后沒有這個(gè)配置,需要自己添加)、存放的是 MCP Server 的地址;
Pilot 連接 MCPServer 之后發(fā)送所關(guān)注的資源請求;
MCPServer 收到資源請求,檢查請求的版本信息(可能為空),判斷版本信息和當(dāng)前最新維護(hù)的版本信息是否一致,不一致則觸發(fā) Push 操作,一致則不處理;
Pilot 收到 Push 數(shù)據(jù),處理返回的數(shù)據(jù)(數(shù)據(jù)列表可能為空,為空也標(biāo)示處理成功),根據(jù)處理結(jié)果返回 ACK(成功)/ NACK(失敗),返回的應(yīng)答中包含返回?cái)?shù)據(jù)的版本信息,如果返回的是 NACK,Pilot 會(huì)繼續(xù)請求當(dāng)前資源;
MCPServer 收到 ACK(和資源請求一致)之后對比版本號,如果一致則不推送,否則繼續(xù)推送最新數(shù)據(jù);
推送
MCPServer 自身數(shù)據(jù)發(fā)生變化,主動(dòng)推送變化的資源給 Pilot;
Pilot 收到之后處理這些數(shù)據(jù),并根據(jù)處理結(jié)果返回 ACK / NACK;
MCPServer 收到 ACK(和資源請求一致) 之后對比版本號,如果一致則不推送,否則繼續(xù)推送最新數(shù)據(jù);
這樣的訂閱、推送流程就保證了 MCPServer 和 Pilot 資源的一致。MCPServer 只能通過 MCP 協(xié)議告訴 Pilot 資源發(fā)生變化了么?當(dāng)然不是,MCPServer 可以使用創(chuàng)建 CR 的方式,Pilot 通過 Kubernetes 的 Informer 機(jī)制也能感知到資源發(fā)生變化了,只是通過 MCP 傳輸?shù)馁Y源在 Kubernetes 里面看不到,只是存在于 Pilot 的內(nèi)存里面,當(dāng)然也可以通過 Pilot 提供的 HTTP debug 接口(istiod_ip:8080/debug/configz)來查。
https://github.com/champly/mcpserver?提供了一個(gè) MCPServer 的一個(gè) demo,如果需要更加細(xì)致的了解 MCP 原理可以看一看。
更多 debug 接口可以查看:?
https://github.com/istio/istio/blob/5b926ddd5f0411aa50fa25c0a6f54178b758cec5/pilot/pkg/proxy/envoy/v2/debug.go#L103
Pilot
Pilot 負(fù)責(zé)網(wǎng)格中的流量管理以及控制面和數(shù)據(jù)面之前的配置下發(fā),在 Istio 1.5 之后合并了 Galley、Citadel、Sidecar-Inject 和 Pilot 成為 Istiod。我們這里說的是之前 Pilot 的功能,源碼里面 pilot-discovery 的內(nèi)容。
功能
根據(jù)不同平臺(Kubernetes、Console)獲取一些資源,Kubernetes 中使用 Informer 機(jī)制獲取 Node、Endpoint、Service、Pod 變化;
根據(jù)用戶的配置(CR、MCP 推送、文件)觸發(fā)推送流程;
啟動(dòng) gRPC server 用于接受 Sidecar 的連接;
推送流程
記錄變化的資源類型;
根據(jù)變化的資源類型(數(shù)組)整理本地?cái)?shù)據(jù);
根據(jù)變化的資源類型判斷需要下發(fā)的 xDS 資源;
構(gòu)建 xDS 資源,通過 gRPC 下發(fā)到連接到當(dāng)前 Pilot 的 Sidecar;
xDS
Sidecar 通過動(dòng)態(tài)獲取服務(wù)信息、對服務(wù)的發(fā)現(xiàn) API 被稱為 xDS。
協(xié)議部分(ADS、控制資源下發(fā)的順序及返回確認(rèn)的數(shù)據(jù));
數(shù)據(jù)部分(CDS、EDS、LDS、RDS、SDS);
Pilot 資源類型發(fā)生變化需要下發(fā)的 xDS 資源對照:
以上內(nèi)容是根據(jù)源碼整理:
https://github.com/istio/istio/blob/5b926ddd5f0411aa50fa25c0a6f54178b758cec5/pilot/pkg/proxy/envoy/v2/ads_common.go#L97
MOSN
MOSN 是一款使用 Go 語言開發(fā)的網(wǎng)絡(luò)代理軟件,作為云原生的網(wǎng)絡(luò)數(shù)據(jù)平面,旨在為服務(wù)提供多協(xié)議、模塊化、智能化、安全的代理能力。MOSN 是 Modular Open Smart Network 的簡稱。MOSN 可以與任何支持 xDS API 的 Service Mesh 集成,亦可以作為獨(dú)立的四、七層負(fù)載均衡,API Gateway,云原生 Ingress 等使用。
MOSN:https://github.com/mosn/mosn
配置文件:
mosn_config:MOSN 的配置信息;
listener:LDS;
routers:RDS;
cluster:CDS 和 EDS;
listener
其中address就是 MOSN 監(jiān)聽的地址。
filter chains
filter_chains 在 MOSN 里面的network chains,實(shí)現(xiàn)的還有:
fault_inject;
proxy;
tcp_proxy;
和network chains同級的還有l(wèi)istener chains、stream chains, 其中l(wèi)istener chains目前只有original_dst實(shí)現(xiàn)。stream chains可以對請求中的:
StreamSender;
StreamReceiver;
StreamAccessLog;
進(jìn)行BeforeRouteAfterRoute這些關(guān)鍵步驟進(jìn)行修改請求信息。
所有的filter都只有兩種返回結(jié)果:
Continue:如果后面還有?filter?那就執(zhí)行后續(xù)?filter;
Stop:執(zhí)行完當(dāng)前?filter?就不再繼續(xù)執(zhí)行了;
conv
看圖中的配置信息config的內(nèi)容,downstream_protocol和upstream_protocol這里如果配置不一致,就需要協(xié)議轉(zhuǎn)換。比如HTTP1轉(zhuǎn)換為HTTP2,MOSN 就會(huì)先把HTTP1轉(zhuǎn)換為common的中間協(xié)議,然后再把common轉(zhuǎn)換為HTTP2,這樣就實(shí)現(xiàn)了協(xié)議之間的轉(zhuǎn)換。如果需要自己實(shí)現(xiàn)其他協(xié)議轉(zhuǎn)換,那么只需要編寫轉(zhuǎn)換common的內(nèi)容和common轉(zhuǎn)換為當(dāng)前協(xié)議的內(nèi)容即可實(shí)現(xiàn)協(xié)議之間的互轉(zhuǎn)。
proxy
我們再來看filters里面的proxy,這個(gè)就是一個(gè)會(huì)經(jīng)過路由的代理,配置信息里面配置了router_config_name,就是要路由的router名字。
routers
根據(jù)listener里面的proxy的配置信息里面的router_config_name會(huì)找到一個(gè)router,如上圖所示。然后就會(huì)根據(jù)請求里面的domains去匹配virtual_hosts, 這里的domains里面在HTTP里面就會(huì)是host,當(dāng)在 Dubbo 協(xié)議里面我們可以把service(有些地方叫做 interface、target,我們這里統(tǒng)一叫 service) 放到x-mosn-host這個(gè) MOSN 的Header里面,MOSN 就可以根據(jù)這個(gè)去匹配domains。
然后匹配到一個(gè)virtual_hosts之后,就會(huì)得到對應(yīng)的routers,這里又會(huì)根據(jù)match里面的匹配規(guī)則進(jìn)行匹配,HTTP協(xié)議里面可以根據(jù)path、queryparam、header等信息進(jìn)行匹配,具體匹配規(guī)則通過 VirtualService 下發(fā),如果是 Dubbo 協(xié)議,那么可以套用HTTPRoute規(guī)則,然后把 Dubbo 的attachment解析出來當(dāng)作header去用,目前 MOSN 沒有解析attachment,我們自己實(shí)現(xiàn)了一個(gè)。
匹配到了之后會(huì)得到一個(gè)route,圖中所示只有一個(gè)cluster_name,如果是有多個(gè)subset(DestinationRule 定義),那么就會(huì)有weighted_cluster,里面會(huì)有cluster_name和weight構(gòu)成的對象的數(shù)組,例如:
"route":{"weighted_clusters":[{"cluster":{"name":"outbound|20882|green|mosn.io.dubbo.DemoService.workload","weight":20}},{"cluster":{"name":"outbound|20882|blue|mosn.io.dubbo.DemoService.workload","weight":80}}],"timeout":"0s","retry_policy":{"retry_on":true,"retry_timeout":"3s","num_retries":2} }其中weight之和必須為 100(Istio 定義的),必須是非負(fù)數(shù)的整數(shù)。
下面有一些timeout、retry_policy服務(wù)策略。
匹配上了之后會(huì)得到一個(gè)cluster_name,然后我們再看cluster
cluster
在routers里面匹配出來的cluster_name作為key在cluster里面會(huì)找到這么一個(gè)對象。
其中l(wèi)b_type就是節(jié)點(diǎn)的負(fù)載均衡策略,目前 MOSN 支持:
ROUNDROBIN;
RANDOM;
WEIGHTED_ROUNDROBIN;
EAST_REQUEST;
hosts里面的address里面也可以配置權(quán)重,這個(gè)權(quán)重必須是大于 0 或小于 129 的整數(shù)。可以通過 Istio 1.6 里面的WorkloadEntry來配置權(quán)重。然后根據(jù)負(fù)載均衡策略拿到host之后直接請求到對應(yīng)的節(jié)點(diǎn)。
這就完成了流量的轉(zhuǎn)發(fā)。接下來我們看看 Dubbo 場景下應(yīng)該如何改造。
Dubbo 場景下的改造
所有的改造方案里面都是要把 SDK 輕量化,關(guān)于服務(wù)治理的邏輯下沉到 Sidecar,我們在探索的過程中有三種方案。
Istio + Envoy
這個(gè)方案是 Istio+Envoy 的方案,是參考的華為云的方案:?
https://support.huaweicloud.com/bestpractice-istio/istiobestpractice3005.html
通過創(chuàng)建 EnvoyFilter 資源來給 xDS 資源打 patch;
Envoy 解析 Dubbo 協(xié)議中的 Service 和 Method;
根據(jù)路由策略配置把流量轉(zhuǎn)發(fā)到對應(yīng)的 Provider;
這種方案如果需要解析更多的 Dubbo 內(nèi)容,可以通過 WASM 擴(kuò)展。
MOSN + Dubbo-go
MOSN 提供 Subscribe、Unsubscribe、Publish、Unpublish 的 HTTP 服務(wù);
SDK 發(fā)送請求到 MOSN 提供的這些服務(wù),讓 MOSN 代為與真正的注冊中心交互;
MOSN 通過 Dubbo-go 直接和注冊中心連接;
這種方案的話就不需要 Istio。
Istio + MOSN
這種方案就是我們現(xiàn)在采用的方案,包括:
數(shù)據(jù)面改造;
控制面適配;
我們有一個(gè)理念就是如果能通過標(biāo)準(zhǔn)的 CRD 最好,如果描述不了的話我們就通過 EnvoyFilter 進(jìn)行修改。這里特別說一下,我們一開始也有一個(gè)誤區(qū)就是 EnvoyFilter 是作用于 Envoy,其實(shí)不是的,是對生成好的 xDS 資源進(jìn)行 ADD, MERGE 等操作,目前只可以修改 LDS、RDS、CDS,這個(gè)修改也是有一定局限性的。如果 EnvoyFilter 修改不了某些特定的場景(比如 Istio 1.6 之前的 ServiceEntry 里面的 Endpoint 不能單獨(dú)為每個(gè)實(shí)例指定不同的端口),那么我們只能修改 pilot-discovery 的代碼,xDS 是不會(huì)作任何修改的。按照這個(gè)理念,我們開始探索如何改造。
數(shù)據(jù)面改造
首先有三個(gè)端口需要說明一下:
20880 : provider 監(jiān)聽端口;
20881 : consumer 請求 MOSN 的這個(gè)端口,MOSN 做轉(zhuǎn)發(fā)到 provider;
20882 : 接受來自下游(MOSN/consumer)的請求,直接轉(zhuǎn)到 127.0.0.1:20880;
步驟:
provider 啟動(dòng)之后請求本地 MOSN 的注冊接口,把服務(wù)信息注冊到注冊中心(zk/nacos),注冊請求到達(dá) MOSN 之后,MOSN 會(huì)把注冊端口號改為 20882;
consumer 啟動(dòng)之后不需要連接注冊中心,直接把請求發(fā)送到 127.0.0.1:20881;
consumer 端的 MOSN 收到請求之后,根據(jù)配置信息 listener->routers->cluster->host,找到合適的 host(可以是 provider 的 MOSN 或者直接是 provider) 發(fā)送請求,這里的匹配過程可以修改 MOSN 讓 Dubbo 的 service 作為 domains,attachment 作為 header;
provider 端 MOSN 收到請求后(20882),直接轉(zhuǎn)發(fā)請求到本地 127.0.0.1:20880;
這個(gè)只是通過靜態(tài)配置實(shí)現(xiàn)的,如果 provider 這些信息如何通過 Pilot 下發(fā)呢?
控制面適配
MOSN 本身支持 xDS API,配置信息可以通過 xDS 下發(fā),而不是靜態(tài)配置。我們有一個(gè)對接配置中心,注冊中心的程序我們叫 Adapter,這個(gè)主要獲取注冊中心的服務(wù)信息,然后根據(jù)配置中心的服務(wù)治理策略(比如流程比例,還有一些我們內(nèi)部的一些單元的信息)構(gòu)建出 Istio 支持的 CR,然后創(chuàng)建 CR,Pilot 自己感知 CR 變化 或者 通過 MCP 把這些信息直接發(fā)送給 Pilot,觸發(fā) Pilot 的資源變化,然后 Pilot 根據(jù)資源的變化去下發(fā)一些 xDS 資源,Sidecar 收到資源變化后,就可以動(dòng)態(tài)調(diào)整路由策略,從而達(dá)到服務(wù)治理的目的。
最終架構(gòu)圖如圖所示:
注冊(灰色部分):
1. provider 發(fā)送注冊信息給 MOSN;
2. MOSN 修改注冊信息(端口號等),然后注冊到真正到注冊中心(ZK / Nacos 等);
配置下發(fā)(藍(lán)色部分):
1. Adapter 連接注冊中心和配置中心并感知其變化;
2. Adapter 感知到變化之后通過 MCP 把變化的信息傳遞給 Pilot(或者創(chuàng)建 CR 讓 Pilot 自己感知);
3. Pilot 感知到資源變化觸發(fā)配置下發(fā)流程,根據(jù)變化到資源類型下發(fā)對應(yīng)到 xDS 資源到 連接到它的 Sidecar;
服務(wù)請求(黃色部分):
1. consumer 請求本地 127.0.0.1:20881(MOSN 監(jiān)聽的端口);
2. MOSN 根據(jù) listener->router->cluster 找到一個(gè) host,然后把請求轉(zhuǎn)發(fā)到這個(gè) host 上;
以上就完成了服務(wù)注冊、發(fā)現(xiàn)、治理的所有邏輯。
Istio 1.6 之后可以通過 WorkloadEntry + ServiceEntry 這兩種 CRD 資源來描述集群外的服務(wù),當(dāng)實(shí)例上線或者下線的時(shí)候就會(huì)直接觸發(fā) EDS 增量下發(fā)。
Demo 演示
首先要說明一下:
由于沒有真正的注冊,所以使用手動(dòng)添加 ServiceEntry 的方式代替 Adapter 功能;
Listener 和 Routers 配置信息目前是固定的;
Provider 只注冊到本地 ZK;
Sidecar 注入到方式使用的是多個(gè) Container;
具體操作可以按照mosn-tutorial,里面的istio-mosn-adapt-dubbo。即使你沒有 Kubernetes 環(huán)境也可以嘗試的,后期這個(gè)會(huì)移植到 MOSN 官網(wǎng),敬請期待。
mosn-tutorial:https://github.com/mosn/mosn-tutorial
以上就是本期分享的全部內(nèi)容,感謝大家的收看。
本期嘉賓介紹
陳鵬,多點(diǎn)生活平臺架構(gòu)組研發(fā)工程師,開源項(xiàng)目與云原生愛好者。有多年的網(wǎng)上商城、支付系統(tǒng)相關(guān)開發(fā)經(jīng)驗(yàn),2019年至今從事云原生和 Service Mesh 相關(guān)開發(fā)工作。
回顧資料
PPT 下載:
https://github.com/servicemesher/meetup-slides/tree/master/2020/05/webinar
視頻回顧:
https://www.bilibili.com/video/BV15k4y1r7n8
本文歸檔在 sofastack.tech。
?
新炬首架梁銘圖:從70萬字SRE神作提煉出7千字精華與君共勉
?
手把手教你績效管理體系-OKR
?
技術(shù)團(tuán)隊(duì)的工程師文化:效率與價(jià)值
中生代技術(shù)社區(qū)提供內(nèi)推服務(wù),對應(yīng)BAT,網(wǎng)易,頭條等大廠對接到用人部門,
有需求請?zhí)砑尤汉匣锶?strong>大白的微信
申請備注(姓名+公司+技術(shù)方向)才能通過哦!
? ?END ? ?? #接力技術(shù),鏈接價(jià)值#總結(jié)
以上是生活随笔為你收集整理的多点生活在 Service Mesh 上的实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Pyramid Attention Ne
- 下一篇: 在服务器搭建深度学习环境随笔