作者 | 童子龍 掌門教育基礎架構部架構師
導讀:本文整理自作者於 2020 年雲原生微服務大會上的分享《掌門教育雲原生落地實踐》,本文主要介紹了掌門教育雲原生落地實踐,主要圍繞 Spring Cloud Alibaba & Nacos & Sentinel & Arthas 等微服務雲原生技術棧實施構建,基於 Docker 和 阿里雲 Kubernetes 雲原生容器的實現落地,着重介紹 Nacos 服務器高可用性部署、監控,Nacos 和 Eureka 同步服務器高可用雙向同步和容災,以及和 DevOps 運維發布平台的整合。
阿里巴巴雲原生公眾號后台回復 818 即可獲取直播回看地址和大會 PPT 合集。
背景
掌門教育自 2014 年正式轉型在線教育以來,秉承“讓教育共享智能,讓學習高效快樂”的宗旨和願景,經歷雲計算、大數據、人工智能、 AR / VR / MR 以及現今最火的 5G ,一直堅持用科技賦能教育。掌門教育的業務近幾年得到了快速發展,特別是今年的疫情,使在線教育成為了新的風口,也給掌門教育新的機遇。
隨着業務規模進一步擴大,流量進一步暴增,微服務數目進一步增長,使老的微服務體系所采用的注冊中心 Eureka 不堪重負,同時 Spring Cloud 體系已經演進到第二代,第一代的 Eureka 注冊中心已經不大適合現在的業務邏輯和規模,同時它目前被 Spring Cloud 官方置於維護模式,將不再向前發展。如何選擇一個更為優秀和適用的注冊中心,這個課題就擺在了掌門人的面前。
為什么選擇 Spring Cloud Alibaba&Nacos
經過對 Alibaba Nacos 、HashiCorp Consul 等開源注冊中心做了深入的調研和比較,以下是各個注冊中心的特性對比:
- Nacos
- 支持 AP+CP 一致性共識協議
- 支持 Agent DNS-F 服務注冊發現方式,跨語言
- 支持負載均衡,雪崩保護機制
- 支持多數據中心,跨注冊中心遷移
- Consul
- 只支持 CP 協議
- 支持 HTTP/DNS 協議
- K8s CoreDns
- 支持 DNS 協議
結論:Nacos 滿足目前掌門的服務治理技術棧,能實現注冊中心的平滑遷移,社區發展非常活躍,所提供的特性,使得圍繞 Spring Cloud Alibaba&Nacos 能夠非常方便的構建雲原生應用的動態服務注冊發現。
一.Nacos server 落地
1. Nacos Server 部署
(Nacos Server 部署概覽圖)
- Nacos Server 環境和域名
掌門的應用環境分為 4 套,DEV、FAT、UAT、PROD 分別對應開發、測試、准生產環境、生產環境,因此 Nacos Server 也分為 4 套獨立環境。除了 DEV 環境是單機部署外,其他是集群方式部署。對外均以域名方式訪問,SLB 做負載均衡,包括 SDK 方式連接 Nacos Server 和訪問 Nacos Server Dashboard 控制台頁面。
- Nacos Server 環境隔離和調用隔離
Nacos 數據模型由 namespace / group / service 構成。 可以通過創建不同的命名空間,做到同一個應用環境的基礎上更細粒度的划分,隔離服務注冊和發現。在某些場景下,開發本地有需要連接測試環境的 Nacos Server ,但其他測試服務不能調用到開發本地,這時候可以將 NacosDiscoveryProperties 的 enabled 屬性設置為 false 。
- Nacos Server 集成 Ldap
Nacos Server Dashboard 集成公司的 Ldap 服務,並在用戶首次登錄時記錄用戶信息。
2. Nacos Server 界面
- Nacos 界面權限
Nacos Server Dashboard 用戶首次登陸時,默認分配普通用戶(即非 ROLE_ADMIN )角色,對查詢以外的按鈕均無操作權限,以免出現誤操作導致服務非正常上下線。
- Nacos 界面顯示服務概覽
Nacos Server Dashboard 頁面增加服務總數及實例總數的統計,該信息每 5 秒刷新一次。
3. Nacos 監控
- 標准監控
基於公司現有的 Prometheus 、 Grafana 、 AlertManager 從系統層監控 Nacos。
- 高級監控
根據 Nacos 監控手冊,結合 Prometheus 和 Grafana 監控 Nacos 指標。
- 服務實例狀態監控
- 監聽實例下線事件
- 監聽實例注銷事件
- 監聽實例注冊事件
- 監聽實例上線事件
- 監聽實例心跳超時事件
4. Nacos 日志
- 日志合並及 JSON 格式化
將 Nacos 多模塊的日志統一按 info 、 warn、error 級別合並,定義 schema 字段標記不同模塊,按 JSON 格式滾動輸出到文件,供 ELK 采集展示。
5. Nacos 告警
- 業務服務上下線的告警
- 服務名大寫告警
6. Nacos 性能測試
- 核心腳本
def registry(ip):
fo = open("service_name.txt", "r")
str = fo.read()
service_name_list = str.split(";")
service_name = service_name_list[random.randint(0,len(service_name_list) - 1)]
fo.close()
client = nacos.NacosClient(nacos_host, namespace='')
print(client.add_naming_instance(service_name,ip,333,"default",1.0,{'preserved.ip.delete.timeout':86400000},True,True))
while True:
print(client.send_heartbeat(service_name,ip,333,"default",1.0,"{}"))
time.sleep(5)
- 壓測數據
- 壓測結果圖
總結:Nacos Server 是 3 台 1C4G 集群,同時承受 1499 個服務和 12715 個實例注冊,而且 CPU 和內存長期保持在一個合適的范圍內,果真 Nacos 性能是相當 OK 的。
二.Nacos Eureka Sync 落地
1. Nacos Eureka Sync 方案選型
① Sync 官方方案
經過研究,我們采取了官方的 Nacos Eureka Sync 方案,在小范圍試用了一下,效果良好,但一部署到 FAT 環境后,發現根本不行,一台同步服務器無法抗住將近 660 個服務(非實例數)的頻繁心跳,同時該方案不具備高可用特點。
② Sync 高可用一致性 Hash + Zookeeper 方案
既然一台不行,那么就多幾台,但如何做高可用呢?
我們率先想到的是一致性 Hash 方式。當一台或者幾台同步服務器掛掉后,采用 Zookeeper 臨時節點的 Watch 機制監聽同步服務器掛掉情況,通知剩余同步服務器執行 reHash ,掛掉服務的工作由剩余的同步服務器來承擔。通過一致性 Hash 實現被同步的業務服務列表的平均分配,基於對業務服務名的二進制轉換作為 Hash 的 Key 實現一致性 Hash 的算法。我們自研了這套算法,發現平均分配的很不理想,第一時間懷疑是否算法有問題,於是找來 Kafka 自帶的算法(見 Utils.murmur2 ),發現效果依舊不理想,原因還是業務服務名的本身分布就是不平均的,於是又回到自研算法上進行了優化,基本達到預期,下文會具體講到。但說實話,直到現在依舊無法做到非常良好的絕對平均。
③ Sync 高可用主備 + Zookeeper 方案
這個方案是個小插曲,當一台同步服務器掛掉后,由它的“備”頂上,當然主備切換也是基於 Zookeeper 臨時節點的 Watch 機制來實現的。后面討論下來,主備方案,機器的成本很高,實現也不如一致性 Hash 優雅,最后沒采用。
④ Sync 高可用一致性 Hash + Etcd 方案
折騰了這么幾次后,發現同步業務服務列表是持久化在數據庫,同步服務器掛掉后 ReHash 通知機制是由 Zookeeper 來負責,兩者能否可以合並到一個中間件上以降低成本?於是我們想到了 Etcd 方案,即通過它實現同步業務服務列表持久化 + 業務服務列表增減的通知 + 同步服務器掛掉后 ReHash 通知。至此方案最終確定,即兩個注冊中心( Eureka 和 Nacos )的雙向同步方案,通過 Etcd 來做橋梁。
2. Nacos Eureka Sync 落地實踐
① Nacos Eureka Sync 目標原則
注冊中心遷移目標:
- 過程並非一蹴而就的,業務服務逐步遷移的過程要保證線上調用不受影響,例如, A 業務服務注冊到 Eureka 上, B 業務服務遷移到 Nacos ,A 業務服務和 B 業務服務的互相調用必須正常;
- 過程必須保證雙注冊中心都存在這兩個業務服務,並且目標注冊中心的業務服務實例必須與源注冊中心的業務服務實例數目和狀態保持實時嚴格一致。
注冊中心遷移原則:
- 一個業務服務只能往一個注冊中心注冊,不能同時雙向注冊;
- 一個業務服務無論注冊到 Eureka 或者 Nacos,最終結果都是等效的;
- 一個業務服務在絕大多數情況下,一般只存在一個同步任務,如果是注冊到 Eureka 的業務服務需要同步到 Nacos,那就有一個 Eureka -> Nacos 的同步任務,反之亦然;在平滑遷移中,一個業務服務一部分實例在 Eureka 上,另一部分實例在 Nacos 上,那么會產生兩個雙向同步的任務;
- 一個業務服務的同步方向,是根據業務服務實例元數據( Metadata )的標記 syncSource 來決定。
② Nacos Eureka Sync 問題痛點
- Nacos Eureka Sync 同步節點需要代理業務服務實例和 Nacos Server 間的心跳上報。Nacos Eureka Sync 將心跳上報請求放入隊列,以固定線程消費,一個同步業務服務節點處理的服務實例數超過一定的閾值會造成業務服務實例的心跳發送不及時,從而造成業務服務實例的意外丟失;
- Nacos Eureka Sync 節點宕機,上面處理的心跳任務會全部丟失,會造成線上調用大面積失敗,后果不堪設想;
- Nacos Eureka Sync 已經開始工作的時候,從 Eureka 或者 Nacos 上,新上線或者下線一個業務服務(非實例),都需要讓 Nacos Eureka Sync 實時感知。
③ Nacos Eureka Sync 架構思想
- 從各個注冊中心獲取業務服務列表,初始化業務服務同步任務列表,並持久化到 Etcd 集群中;
- 后續遷移過程增量業務服務通過 API 接口持久化到 Etcd 集群中,業務服務遷移過程整合 DevOps 發布平台。整個遷移過程全自動化,規避人為操作造成的遺漏;
- 同步服務訂閱 Etcd 集群獲取任務列表,並監聽同步集群的節點狀態;
- 同步服務根據存活節點的一致性 Hash 算法,找到處理任務節點,后端接口通過 SLB 負載均衡,刪除任務指令輪詢到的節點。如果是自己處理任務則移除心跳,否則找到處理節點,代理出去;
- 同步服務監聽源注冊中心每個業務服務實例狀態,將正常的業務服務實例同步到目標注冊中心,保證雙方注冊中心的業務服務實例狀態實時同步;
- 業務服務所有實例從 Eureka 到 Nacos 后,需要業務部門通知基礎架構部手動從 Nacos Eureka Sync 同步界面摘除該同步任務。
④ Nacos Eureka Sync 集群分片及高可用方案
服務一致性 Hash 分片路由:
- 根據如上圖 1 多集群部署,為每個節點設置可配置的虛擬節點數,使其在 Hash 環上能均勻分布;
- 根據業務服務名的 FNV1_32_HASH 算法計算每個業務服務的哈希值,計算該 Hash 值順時針最近的節點,將任務代理到該節點。
同步節點宕機故障轉移:
- 節點監聽:監聽其它節點存活狀態,配置 Etcd 集群租約 TTL , TTL 內至少發送 5 個續約心跳以保證一旦出現網絡波動避免造成節點丟失;
- 節點宕機:其中某個節點宕機,其任務轉移到其它節點,因為有虛擬節點的緣已經故,所以此節點的任務會均衡 ReSharding 到其它節點,那么,集群在任何時候,任務處理都是分片均衡的,如上圖 2 中, B 節點宕機, ##1 、 ##2 虛擬節點的任務會分別轉移到 C 和 A 節點,這樣避免一個節點承擔宕機節點的所有任務造成剩余節點連續雪崩;
- 節點恢復:如圖 3,節點的虛擬節點重新添加到 Hash 環中, Sharding 規則變更,恢復的節點會根據新的 Hash 環規則承擔其它節點的一部分任務,心跳任務一旦在節點產生都不會自動消失,這時需要清理其它節點的多余任務(即重新分配給復蘇節點的任務),給其它節點減負(這一步非常關鍵,不然也可能會引發集群的連續雪崩),保障集群恢復到最初正常任務同步狀態;
- 節點容災:如果 Etcd 集群連接不上,則存活節點從配置文件中獲取,集群正常運作,但是會失去容災能力。
3. Nacos Eureka Sync 保障手段
① Nacos Eureka Sync 同步界面
從如下界面可以保證,從 Eureka 或者 Nacos 上,新上線或者下線一個業務服務(非實例),都能讓 Nacos Eureka Sync 實時感知。但我們做了更進一層的智能化和自動化:
-
新增同步:結合 DevOps 發布平台,當一個業務服務(非實例)新上線的時候,智能判斷它是從哪個注冊中心上線的,然后回調 Nacos Eureka Sync 接口,自動添加同步接口,例如,A 業務服務注冊到 Eureka 上,DevOps 發布平台會自動添加它的 Eureka -> Nacos 的同步任務,反之亦然。當然從如下界面的操作也可實現該功能;
-
刪除同步:由於 DevOps 發布平台無法判斷一個業務服務(非實例)下線,或者已經遷移到另一個注冊中心,已經全部完畢(有同學會反問,可以判斷的,即查看那個業務服務的實例數是否是零為標准,但我們應該考慮,實例數為零在網絡故障的時候也會發生,即心跳全部丟失,所以這個判斷依據是不嚴謹的),交由業務人員來判斷,同時配合釘釘機器人告警提醒,由基礎架構部同學從如下界面的操作實現該功能。
② Nacos Eureka Sync Etcd 監控
從如下界面可以監控到,業務服務列表是否在同步服務的集群上呈現一致性 Hash 均衡分布。
③ Nacos Eureka Sync 告警
- Nacos Eureka Sync 告警
- 業務服務同步完畢的告警
4.Nacos Eureka Sync 升級演練
- 7 月某天晚上 10 點開始, FAT 環境進行演練,通過自動化運維工具 Ansible 兩次執行一鍵升級和回滾均沒問題;
- 晚上 11 點 30 開始,執行災難性操作,觀察智能恢復狀況, 9 台 Nacos Eureka Sync 掛掉 3 台的操作,只丟失一個實例,但 5 分鍾后恢復(經調查,問題定位在 Eureka 上某個業務服務實例狀態異常);
- 晚上 11 點 45 開始,繼續掛掉 2 台,只剩 4 台,故障轉移,同步正常;
- 晚上 11 點 52 開始,恢復 2 台,Nacos Eureka Sync 集群重新均衡 ReHash ,同步正常;
- 晚上 11 點 55 開始,全部恢復,Nacos Eureka Sync 集群重新均衡 ReHash ,同步正常;
- 12 點 14 分,極限災難演練, 9 台掛掉 8 台,剩 1 台也能抗住,故障轉移,同步正常;
- 凌晨 12 點 22 分,升級 UAT 環境順利;
- 凌晨 1 點 22,升級 PROD 環境順利;
- 容災恢復中的 ReHash 時間小於 1 分鍾,即 Nacos Eureka Sync 服務大面積故障發生時,恢復時間小於 1 分鍾。
三.Solar 雲原生微服務實踐
(Solar 雲原生微服務體系)
Solar 微服務體系,囊括微服務治理組件,中間件以及基礎組件易用性封裝,告警監控體系等,連接着掌門業務服務和底層基礎設施,每項服務都遵守強有力的合約,向着雲原生微服務架構方向演進。
1. 基於 Spring Cloud Alibaba、Nacos、Sentinel 等 SDK
① Alibaba Nacos
- Solar Nacos SDK 內置 DEV | FAT | UAT | PROD 四個環境的域名,業務系統無感知 Solar Nacos SDK 基於 Spring Cloud Alibaba 整合攜程 VI Cornerstone 實現微服務點火熄火拉入拉出;
- Solar Nacos SDK 在 Nacos 和 Eureka 雙注冊中心過渡狀態下, 支持跨注冊中心調用的藍綠灰度發布和子環境功能;
- Solar Nacos SDK 集成灰度藍綠埋點到 SkyWalking;
- Solar Nacos SDK 通過 @EnableSolarService , @EnableSolarGateway 封裝了標准 Spring Boot / Spring Cloud / Apollo / Zuul 等大量注解,降低業務的使用成本;
- Solar Nacos SDK 和 Solar Eureka SDK 升級和回滾;
- Solar Nacos SDK 結合 Java Agent 方式,解決異步調用場景下的跨線程調用的上下文丟失。
② Alibaba Sentinel
- Solar Sentinel SDK 內置 DEV | FAT | UAT | PROD 四個環境的域名,業務系統無感知
- SDK通過獲取當前機器所在的環境,適配當前所要連接的Sentinel地址
- Solar Sentinel SDK 深度集成 Apollo SDK
- Sentinel配置,持久化到服務的apollo的namespace下面,下次重啟從apollo獲取配置加載到內存
- 以appId的維度配置應用熔斷限流規則
- Solar Sentinel SDK 整合 OpenTracing & SkyWalking,輸出 Sentinel 埋點到 SkyWalking
- 通過SkyWalking提供的OpenTracing 工具包,手動埋點,獲取span信息,推送到SkyWalking持久化到ES
- Solar Sentinel SDK Dashboard 持久化改造,集成 InfluxDB & Grafana
- 將Sentinel Metrics數據持久化到時序數據庫InfluxDB中,然后通過Grafana 展示
- Solar Sentinel SDK Limit-App 熔斷擴展 (特色功能:灰度藍綠發布指標的熔斷)
- 灰度藍綠調用時,如果探測到版本匹配失敗時,則拋BlockException
- Solar Sentinel SDK 網關流控 ,微服務單機限流
- 全鏈路壓測幫助了解服務能承載流量峰值
- 信號量隔離/QPS, 並發線程數限流/平均響應時間、秒級異常比率、分鍾級異常數熔斷
- 基於 TCP BBR 的系統保護算法,自動探測系統瓶頸,保護系統穩定性
- Solar Sentinel SDK 集群限流
- 通過集群限流來解決集群各個機器的流量不均導致整體限流效果不精確的問題
2. 灰度藍綠和環境隔離
- 基於 Spring Cloud Alibaba 、Nacos SDK、Nepxion Discovery 開源框架(https://github.com/Nepxion/Discovery)
- 藍綠灰度發布 :版本匹配灰度發布、版本權重灰度發布
- 多區域路由:區域匹配灰度路由、區域權重灰度路由
- 環境隔離:環境隔離、環境路由
3. 基於 DevOps 發布平台的智能化和半自動化灰度藍綠
- **智能化發布入口界面 **
- 藍綠條件驅動模式界面
- 藍綠權重放量模式界面
- 全量發布和回滾界面
4. 基於 DevOps 發布平台的滾動無損發布
- 運維 CD 發布平台,先將實例狀態設置 disabled ,實例從注冊中心拉出;
- 消費者訂閱注冊中心,通知消費者實例處於不可用狀態;
- 消費者停止路由轉發到不可用實例;
- 服務上面流量繼續處理,30S 后才會啟動實例發布腳本;
- 實例重啟成功后,CD 平台通過請求寄宿在業務 Web 容器里的 VI 接口檢測實例健康狀態;
- 狀態檢測健康后,注冊到 Nacos 注冊中心;
- 消費者訂閱到新的實例,請求正常負載。
5. 分布式追蹤和 APM 系統 SkyWalking
- 所有服務異常監控大盤
- 接口性能指標
- 服務維度的異常監控看板,聚合鏈路中異常數量,幫助業務快速定位問題
- 集成 Solar 全鏈路灰度藍綠埋點
- 集成 Sentinel 限流降級熔斷埋點
- 整合服務、實例、接口維度性能指標
- 快速定位異常、慢 SQL、熔斷鏈路
- 整合鏈路與日志
- 服務、實例、接口、鏈路維度拓撲圖
- 整合應用診斷系統(Arthas & Bistoury)
6. 應用診斷系統 Arthas & Bistoury
- 無需登錄機器
- 整合 Arthas,Web 化控制台 從 CPU 、線程、內存、JVM 等方面對應用進行診斷
- 熱點方法分析
- 在線 Debug
四. Solar 雲原生容器化實踐
1. CI/CD 持續發布
- CD Platform 通過 jinkens 編譯打包生成 Jar 包和 Docker img,通過 Harbor 上傳鏡像到 OSS 平台,Harbor 通過 SLB 做高可用;
- 自研 Hyperion 中間服務,作為連接 Harbor 和阿里雲 K8s 的 API 調用中間層;
- CD Platform 通過 Hyperion 調用阿里雲 K8s API 發布鏡像,K8s 從 Harbor 拉取鏡像,deploy 到物理節點;
- 阿里雲 K8s 推送狀態事件給 Hyperion,Hyperion 將數據推送給 .CD Platform 實時展示發布狀態信息。
2. 日志收集
- Pod 將日志寫到容器內的路徑 /opt/logs/{appid}/xxx;
- 建立軟連接指向 Node 路徑 /var/log/{appid}/{podid}/xxx;
- 一個物理節點啟動一個 FileBeat 進程收集此物理節點上所有 Pod 日志信息;
PS:經過全面的壓測,一個物理節點上啟動一個 FileBeat 進程收集所有 Pod 日志,性能沒有問題
如果存在日志收集不及時問題,則可以一個 Pod 掛載一個 FileBeat 進程來解決,這樣的缺點是會占用更多系統資源。
- FileBeat 將日志信息推送到 Kafka;
- GoHangout 並發消費 Kafka 中數據,持久化到 ES 集群中;
GoHangout 並發消費 Kafka 消息性能比較好。
- Kibana 顯示 ES 中所有日志索引數據。
3. 微服務彈性擴容和自愈
- CPU 負載
- Memory
- Metrics:根據熔斷、限流、監控等組件提供的 Metric 指標做彈性伸縮和自愈;
- 根據課堂排課信息的容量規划:如下圖掌門上課情況非常規律,流量峰值也規律分布,根據排課信息等數據來規划未來幾小時內微服務需要承載容量,並按照計划,分配 Pod 數量
4. 平滑遷移網絡解決方案
- 阿里雲 Terway Kubernetes 集群提供 CNI Plugin 實現 Pod IP、Node IP 處於同一平面;
- Pod 每次發布 IP 都會發生變化,內網沿用虛擬機時代的訪問和治理方案;
- 外網訪問通過阿里雲 SLB,SLB 能自動探測 IP 變化;
- 基礎架構在微服務構建上面已經有很深的積累,充分利用 Spring Cloud Alibaba 以及 Nacos 等一系列服務治理方案 ,使我們雲原生容器化過程能夠平滑遷移到阿里雲 K8s。
結語:以上就是掌門教育圍繞 Spring Cloud Alibaba 構建雲原生微服務技術體系的一個全貌,掌門教育也會跟隨社區技術發展的腳步,朝着微服務 Service Mesh 網格化,serverless 函數計算的方向不斷演進,很多年前,大家可能在討論服務上雲的風險,隨着雲原生技術的不斷成熟,現在大家更多的是討論服務不上雲的風險,希望此次分享能給那些准備使用 Spring Cloud Alibaba 微服務系上雲的或者正在上雲的同學一些實用性的參考和指引,謝謝大家!
Spring Cloud Alibaba 七天訓練營火熱開營!
PC 端點擊鏈接了解詳情:https://developer.aliyun.com/learning/trainingcamp/spring/1
“阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公眾號。”