得物社群 golang 灰度環境探索和實踐
1
背景
灰度釋出可以在服務正式上線前,提前用小流量對新功能進行驗證,提前發現問題,避免故障影響所有使用者,對業務穩定性非常有價值。
得物社群後端技術棧以 golang 為主,本文記錄了社群後端在灰度環境建設過程中遇到的挑戰,以及對應的探索和實踐。
名詞解釋
小得物:得物內部小流量灰度環境。 ARK:得物內部配置中心。 DLB:得物內部負載均衡中介軟體。 DMQ:得物內部訊息中介軟體。 DRPC:golang 後端 RPC 系統。
2
小得物灰度引流架構最佳化
2.1 小得物 V1
小得物可以只部署部分應用。 未部署小得物的 HTTP 入口應用,HTTP 流量導向生產。 未部署小得物的 gRPC 下游應用,gRPC 流量導向生產。
要實現小得物環境只部署部分應用,正確路由流量而不報錯,需要閘道器層、RPC 等呼叫層感知叢集內後端服務有沒有部署。
Ingress 這層,其實相當於接了 k8s 的註冊中心,它是可以感知到叢集是否有可用 upstream。但開源配置無法支援這個需求,二開比較複雜,這個也不在社群的控制範圍內。
這個時期社群應用正在進行容器新老叢集遷移,在容器 Ingress 之前加了一層 DLB(可以簡單理解為 Nginx),透過 location 來區分應用是否部署新叢集,以及新老叢集流量灰度。
年中時社群第一批約 15 個 C 端應用上線小得物,同時對小得物環境的監控告警等基礎設施進行了完善。
2.2 小得物 V2
V1 的核心問題在於引流機制是 DNS。DNS 的優勢在於它是在客戶端生效,是去中心化的。但也有很多缺點,比如控制維度單一,只有客戶端 IP、地域。只依靠這個,灰度流量大小難以精準控制,想要的基於 UID、header 的灰度規則也沒法實現。
想要做 UID 灰度引流,一般都是在入口閘道器上做。灰度配置可能經常需要開關、調整流量大小,如果配置錯誤或出現 bug,則影響所有流量。
因此想到一個折中的方案,從生產 DLB 根據 UID 引入 5% 灰度流量至小得物 DLB,小得物上再透過二次灰度規則控制流量大小在 0-5%。最大流量限定為 5%,生產只配置一次,後續開關、規則調整均在小得物 DLB 上進行。雖然多用了一個 DLB,但減少生產 DLB 配置變更頻率,縮小了爆炸半徑。
之前做新老叢集遷移的生產 DLB,本來準備下掉,現在正好可以利用起來。對 DLB 進行了版本升級,配置好灰度規則後,就有了現在 V2 的架構。
架構升級後:
灰度流量可按 uid 規則引入,灰度使用者流量總是進小得物,使用者範圍可控,規則清晰。 灰度流量入口與交易互不影響,流量大小可在 0-5% 範圍內靈活調整。灰度流量規則是透過旁路控制,不在生產主鏈路 DLB 上進行,最大流量值限制為 5%,縮小爆炸半徑。 xdw DLB 配置透過 openAPI 控制,且與釋出平臺打通,小得物新版本釋出可 0-5% 梯度引流驗證。 UID 規則外,新增 header 頭引流規則,測試驗證方便。App 可一鍵切換至小得物,由使用者自由選擇。驗證小得物 api 時帶上 header 頭即可路由至小得物,再加上 trace 2.0 全面覆蓋,方便定位流量路徑。
# uid 路由規則
uidRoute:
start: 2000
end: 2500
# header 頭路由規則
headerRoute:
xdw :
3
釋出流程最佳化
3.1 依賴佇列自動生成
對版本分支、線上分支分別進行靜態掃描。 使用 go 標準庫的 parser 包將其解析 為 AST 語法樹,根據查詢 proto client 樁程式碼包引用生成單應用 RPC 呼叫依賴圖。 將兩個版本依賴圖進行 diff,找出版本變化部分。 將版本所有應用的依賴圖進行關聯,最終生成版本依賴圖。
同時與釋出平臺打通,釋出時觸發靜態分析,自動生成釋出依賴狀態圖。以前都是版本 owner 手動畫這個圖,在辦公溝通群眾同步。透過自動化手段,大幅提高了效率和使用者體驗。
在前文提到的小得物 V2 架構中,灰度流量在社群小得物 DLB 中控制。因此在小得物釋出過程中,可以直接透過 openAPI 將小得物流量摘除。沒有了流量,就可以無視應用間依賴,直接批次將所有應用併發部署,大幅提高小得物環境部署效率。
同時摘流後,再透過 API 將流量梯度拉昇,從 0% 緩慢提升至 5%,每次引流都會觸發穩定生產 SOS 事件中心的自動巡檢,根據配置的巡檢規則,計算出得分,展示與七天平均值偏差較大的異常點,幫助版本 owner 提前發現灰度問題。
效果圖:
4
全鏈路灰度
RPC 路由這個功能,大多資料 RPC 呼叫系統都有。社群目前的 RPC 是基於 grpc-go 擴充套件實現的,很多人都說 grpc 沒有服務治理功能,但實際上 grpc 有著良好的擴充套件性和豐富的生態。得物 go 框架基於 grpc-go 只用了千餘行程式碼即可實現擁有服務發現、多註冊中心、多服務名、地址路由、自定義 interceptor 等完備功能的 RPC 呼叫系統。
env == "xdw"
,優先路由至小得物節點,在下游服務未部署小得物時兜底至生產節點,保證可用性。metadata: env: xdwregistries: # grpc 協議 nacos-grpc: type: nacos-grpc url: 協議 nacos-http: type: nacos-http url: 備用註冊中心 nacos-bak: type: nacos-grpc url: 服務 java-nacos: type: java-dubbo url: 多註冊中心引用 - nacos-grpc - nacos-bak direct: type: direct priority: 15client: requestTimeout: 700 pickers: - target: "*" desc: "優先使用小得物地址" match: tag: env == "xdw" - target: "*" desc: "兜底,無小得物地址時使用所有地址" match: tag: "*" targetMap: sns-aaa: services: # 多服務名 - registryName: muilti-nacos serviceName: sns-aaa - registryName: nacos-http serviceName: sns-aaa-http sns-bbb: services: - registryName: muilti-nacos serviceName: sns-bbb # java dubbo 服務 java-ccc: services: - registryName: java-nacos serviceName: "com.xxx.DubboTestGrpcServiceGrpc$ITestGrpcService:1.0:" # 直連地址 direct-ddd: services: - registryName: direct serviceName: ddd.xxx.com:8080
drpc:
remoteConfig:
type: ark
url:
client:
targetMap:
sns-aaa:
# 超時配置
methodTimeout:
AaaService/FooMethod: 100
sns-bbb:
methodTimeout:
BbbService/BarMethod: 50
社群小得物與生產環境公用一套 DB、 MQ 中介軟體。應用程式碼中 MQ producer、comsuer,HTTP、GRPC API 是在一個程式中。如果訊息沒有隔離邏輯,小得物開啟消費,則會與生產節點成為同級消費者,消費生產訊息。而小得物環境機器配置較低,消費速度慢會影響業務。
在沒有 MQ 訊息隔離前,採取一個笨辦法,直接關閉小得物 MQ 消費。但這樣小得物的訊息是靠生產處理,在小得物有 MQ 相關新版本變更時,需要考慮新老相容的問題。
隨著社群阿里雲 MQ 遷移 DMQ 進入收尾階段,DMQ Go SDK 也趨於穩定,開始嘗試使用程式化方案解決 MQ 灰度消費的問題。
最開始跟小得物團隊瞭解了一下最初的方案,小得物和生產使用不同的 MQ 例項,這樣就要求 producer、consumer 在小得物全量部署。對於跨業務域的 topic 需要訊息同步機制。感覺複雜度過高,資源成本和維護成本都很高。
後面看到一篇 阿里雲分享的 RocketMQ 灰度方案,其採用訊息打標、group 隔離、SQL 屬性過濾實現訊息灰度,感覺這才是理想的方案。
這裡說一下 tag 過濾和 SQL 過濾,tag 過濾大家比較常用,但一條訊息只能有一個 tag,常被業務佔用,且不能支援 != 這樣的條件。而 SQL 過濾就靈活得多,可以使用訊息 properties 自定義 kv 鍵值對,SQL 的 NOT、BETWEEN、IN 等關鍵詞都可以使用。
找中介軟體團隊溝通,他們表示 SQL 過濾效能較差,暫不支援。建議使用 Java 染色環境類似的方案,在客戶端過濾。雖然客戶端過濾,有很多無效的網路傳輸,但成本較低,只需要改造一下業務框架中 MQ SDK 即可,也能解決 MQ 灰度的問題。經過壓測,小得物環境過濾生產環境高 QPS 生產的訊息或是 group 積壓的大量訊息, 對應用不會造成較大的效能影響,於是採用了此方案。
4.2.1 訊息消費 consumer 隔離
consumer 消費的隔離比較簡單,MQ 的機制是不同 group 訊息消費都是獨立的,每個 group 都能收到topic 全量訊息。
在業務框架中根據染色環境配置,增加不同的處理邏輯。
如果是染色環境(小得物):
producer 傳送訊息時,在訊息 properties 中新增流量標 X-Flow-Flag=[prefix]。
consumer 啟動時自動給配置的 group 新增 [prefix]。消費時過濾掉 properties 不包含流量標 X-Flow-Flag=[prefix] 的訊息,直接 ack。
trafficRoute: colorEnv: xdw
producer 傳送訊息時,無特殊處理。 consumer 啟動時使用配置中的 group。消費時過濾掉 properties 包含流量標 X-Flow-Flag=[prefix] 的訊息,直接 ack。
trafficRoute: excludeEnvList: [xdw]
4.2.2 事務訊息 producer 隔離
檢視了一下 DMQ 的 Java 原始碼,發現 Boroker 回查時是透過訊息 properties 中的 group 來查詢線上 producer。那麼跟 consumer 類似,給 trans producer 配上 group ,給小得物 group 加上環境字首即可實現事務回查隔離。用於 trans producer 的 group 只是一個標識,甚至不需要在 DMQ 後臺申請。
5
總結
在業務穩定性上,能在正式上線前發現了一些測試、預發環境難以發現的問題,縮小影響範圍,減少上線出問題後匆忙排查、緊急回滾的緊張時刻,降低了系統風險。 在開發效率上,透過摘流批次釋出、依賴梯隊自動生成、釋出流程編排等手段,大大降低了版本釋出人力和時間成本。以前版本十來個應用釋出,需要多個開發介入,前後依賴等待、觀察,耗費較大人力,生產釋出需要 4 個小時以上;現在由一個版本 owner 負責,在小得物驗收透過後,一鍵釋出至生產環境,小得物加生產在 2 個小時內能搞定。幾乎解放了 0.5 天的時間,開發可以把這個時間投入到下個版本的技術方案設計上去。
和前端同學合作,打通中後臺、H5 頁面前後端灰度鏈路。 涉及外部業務域、資料同步中介軟體等場景的 MQ 訊息和灰度流量閉環。 擴大灰度視窗期,下探“深水區”,最佳化QA驗證和產品走查流程。 最佳化開發使用者體驗,降低小得物環境維護成本。例如:抽出小得物、生產公共配置,只維護一份。
*文/ 無風
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024924/viewspace-2939561/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 得物染色環境落地實踐
- 商家視覺化埋點探索和實踐|得物技術視覺化
- 得物App資料模擬平臺的探索和實踐APP
- 基於 Istio 的全鏈路灰度方案探索和實踐
- 得物技術埋點自動化驗證的探索和最佳實踐
- 網易智慧企業 Node.js 實踐(3)| 灰度環境和應用監控Node.js
- 訂單流量錄製與回放探索實踐|得物技術
- 得物直播低延遲探索 | 得物技術
- 分散式全鏈路灰度釋出的探索與實踐分散式
- 小紅書社群反作弊探索與實踐
- 得物社群計數系統設計與實現
- Docker環境部署Prometheus實踐DockerPrometheus
- 得物商家域精準測試實踐
- 得物大模型平臺接入最佳實踐大模型
- 雲原生灰度更新實踐
- 得物前端巡檢平臺的建設和應用實踐前端
- golang環境搭建macGolangMac
- golang環境安裝Golang
- 得物自研API閘道器實踐之路API
- 得物技術多興趣召回模型實踐模型
- Redis叢集環境搭建實踐Redis
- Vagrant 搭建開發環境實踐開發環境
- 分散式中灰度方案實踐分散式
- 【唯實踐】容器環境應用一鍵拉起實踐
- Centos下搭建golang環境CentOSGolang
- Golang GRPC 環境 問題GolangRPC
- visual studio golang環境配置Golang
- golang-wasm 環境搭建GolangASM
- 得物大模型平臺,業務效果提升實踐大模型
- 編譯環境 Golang開發環境 vscode+git編譯Golang開發環境VSCodeGit
- 美團BERT的探索和實踐
- 最佳實踐丨雲開發CloudBase多環境管理實踐Cloud
- GOLang開發環境搭建(Windows)Golang開發環境Windows
- Vscode配置golang開發環境VSCodeGolang開發環境
- golang 入門之環境搭建Golang
- 手把手教你搭建一個灰度釋出環境
- 得物複雜 C 端專案的重構實踐
- 得物技術時間切片的實踐與應用