波司登云原生微服務(wù)治理探索
01
背景
Aliware
波司登創(chuàng)始于1976年,專注于羽絨服的研發(fā)、設(shè)計、制作,是全球知名的羽絨服生產(chǎn)商。波司登用一系列世人矚目的輝煌成績證明了自己的實力:連續(xù)26年全國銷量領(lǐng)先,連續(xù)22年代表中國向世界發(fā)布防寒服流行趨勢,產(chǎn)品暢銷美國、法國、意大利等72個國家,全球超過2億用戶。作為羽絨服革命的旗手,波司登引領(lǐng)了行業(yè)內(nèi)的“三次革命”。
在產(chǎn)品力和銷售成績單背后,波司登在生產(chǎn)、倉儲、物流、銷售各環(huán)節(jié)已完成數(shù)字化轉(zhuǎn)型和創(chuàng)新改造。除生產(chǎn)端的智能生產(chǎn)工廠,波司登對倉儲和物流環(huán)節(jié)也進行智能化改造,提升小單快反、拉式補貨的比重,最大限度減少困擾服裝企業(yè)多時的“庫存”問題;為了精準分發(fā)銷售端產(chǎn)品,波司登建立數(shù)據(jù)中臺,打通全渠道數(shù)據(jù),賦能消費者研究、商品企劃、渠道匹配等。現(xiàn)在,波司登每件羽絨服從生產(chǎn)到抵達消費者,背后都是一段數(shù)字之旅。 02
云原生技術(shù)發(fā)展
Aliware
隨著波司登數(shù)字業(yè)務(wù)的飛速發(fā)展,背后的 IT 技術(shù)也在不斷更新迭代。波司登極為重視客戶對服務(wù)的體驗,并將系統(tǒng)穩(wěn)定性、業(yè)務(wù)功能的迭代效率、問題的快速定位和解決視為構(gòu)建核心競爭力的基石。服飾行業(yè)會積極參與各大電商平臺的促銷活動,業(yè)務(wù)流量的波峰波谷現(xiàn)象明顯,如果由于資源分配不合理導致高峰時期訂單溢出、運力不足,會極大影響顧客和商家的體驗。此外,波司登自研了用戶運營平臺(用戶洞察系統(tǒng)、內(nèi)容管理系統(tǒng)、用戶管理 CRM 系統(tǒng)及用戶小程序)、零售運營平臺(線上平臺訂單管理 OMS 系統(tǒng)、線下渠道管理系統(tǒng)、門店收銀 POS 系統(tǒng))、商品運營平臺(訂單處理中心 OPC、庫存計算中心 ICC、商品訂貨系統(tǒng)、商品運營 iMOS 系統(tǒng)、采購制造 GiMS 系統(tǒng)、物流管理 EWM 系統(tǒng)、機器人調(diào)度 WCS 系統(tǒng)) 等諸多垂直業(yè)務(wù)功能,在市場需求的快速變化下,產(chǎn)品功能創(chuàng)新和迭代效率問題也是對技術(shù)架構(gòu)的一大挑戰(zhàn)。 這些現(xiàn)狀的解法和云原生架構(gòu)帶來的核心能力不謀而合,在波司登系統(tǒng)改造上云的過程中,CIO 戴建國親自帶隊,圍繞著云原生技術(shù)體系,推動波司登的各條業(yè)務(wù)線進行技術(shù)升級改造,加快數(shù)智化發(fā)展進程。在技術(shù)選型上,波司登始終遵循著2條原則:
全面擁抱開源開放的主流技術(shù)標準。 使用開源開放的主流技術(shù)標準可以確保技術(shù)方案的成熟度,更便捷的從開發(fā)者社區(qū)獲取技術(shù)資源和最佳實踐,也能夠幫助企業(yè)更好的招募技術(shù)人才。此外,這樣的策略也避免了被封閉技術(shù)體系和特定云廠商所捆綁。
盡可能利用云計算的價值。 將穩(wěn)定性保障、底層技術(shù)實現(xiàn)、技術(shù)組件維護、彈性伸縮等非功能性需求盡可能交給云廠商解決,讓技術(shù)團隊將更多的精力投入到業(yè)務(wù)創(chuàng)新上。這2個原則并不矛盾,相反,它們之前可以非常好的融合,是所有使用云計算的企業(yè)用戶都值得借鑒的架構(gòu)選型標準。比如 Kubernetes 就是典型的滿足開源開放標準的技術(shù)標準,阿里云提供的 Kubernetes 產(chǎn)品可以簡化用戶的搭建成本,更好的與云計算資源進行集成。同時用戶依然可以基于開源 Kuberntes 的標準協(xié)議與 API 使用云產(chǎn)品,這就是2條選型原則相互融合的最好體現(xiàn)。
03
容器化改造
Aliware
云原生趨勢下,Kubernetes 毫無疑問已經(jīng)成為了企業(yè)新一代云 IT 架構(gòu)的基礎(chǔ)設(shè)施。從2021年開始,波司登就開啟了微服務(wù)和容器化改造計劃,將 IT 系統(tǒng)的底座逐步從虛擬機遷移到 Kubernetes。 在 Kubernetes 平臺的選擇上,基于技術(shù)選型的2條原則,波司登選擇了阿里云容器服務(wù) ACK 。ACK 以阿里云可靠穩(wěn)定的 IaaS 平臺為底座,向下封裝了 30+ 款云產(chǎn)品,形成了自動化運維和云平臺交互的新界面,從而提升企業(yè)業(yè)務(wù)系統(tǒng)的彈性和自動化運維能力。
基于容器服務(wù) ACK 的易用性以及集成能力,波司登IT系統(tǒng)容器化改造工作比預(yù)想中的要順利得多。對于每一個業(yè)務(wù)系統(tǒng)而言,從虛擬機遷移到 Kubernetes ,僅僅是底層的承載發(fā)生了變化,不會涉及到太多的改造成本。在關(guān)鍵的容器網(wǎng)絡(luò)實現(xiàn)上,容器服務(wù) ACK 通過云原生 Terway 網(wǎng)絡(luò)模式,直接基于阿里云的虛擬化網(wǎng)絡(luò)中的彈性網(wǎng)卡資源來構(gòu)建的容器網(wǎng)絡(luò),將容器和虛擬機納入同一層網(wǎng)絡(luò)中,便于業(yè)務(wù)云原生化遷移。這樣完全可以對傳統(tǒng)架構(gòu)實現(xiàn)漸近式容器化改造,在不中斷業(yè)務(wù)的前提下一點一點的從虛擬機往 Kuberntes 上搬。在容器化改造的過程中,當波司登技術(shù)團隊遇到疑難問題的時候,可以第一時間從阿里云獲得最佳實踐指導,包括集群規(guī)劃、平臺運維、應(yīng)用適配、安全防護、可觀測等多個方面,這也更進一步的提升了容器化改造的速度。
目前,波司登的自研系統(tǒng)已經(jīng) 100% 基于 Kubernetes。相比傳統(tǒng)的基于虛擬機部署方式,
容器化幫助波司登在資源利用率上提升了30%,在運維效率上提升了40%。
波司登的技術(shù)團隊也在容器化改造的過程中,掌握了管理超大規(guī)模Kubernetes集群的能力,并促成了更多云原生新技術(shù)的運用。
04
統(tǒng)一微服務(wù)架構(gòu)
Aliware
與容器化改造幾乎同步進行的是對微服務(wù)架構(gòu)的統(tǒng)一。在此之前,波司登的各個業(yè)務(wù)單元多種技術(shù)棧并存,彼此之間相互通訊復(fù)雜度高,項目成員的交接往往要耗費巨大的精力,極大程度上阻礙了數(shù)字化轉(zhuǎn)型的進展,因此微服務(wù)架構(gòu)統(tǒng)一勢在必行。在 CIO 戴建國的帶領(lǐng)下,波司登經(jīng)歷了1年多時間完成了這一項艱巨的工作,雖然投入精力巨大,但收益是立桿見影的,而且可以持續(xù)發(fā)揮作用:不論是內(nèi)部團隊還是三方 ISV ,在技術(shù)框架上都有統(tǒng)一的標準可以遵循,各團隊共享技術(shù)棧后,研發(fā)效率成倍提升。 關(guān)系到未來多年的 IT 戰(zhàn)略,在微服務(wù)架構(gòu)的選型上,高開放性、高成熟度、高普及度這三條標準缺一不可,考慮到波司登以 Java 為主要開發(fā)語言,Spring Cloud Alibaba就成為了微服務(wù)框架的最佳選擇。
Spring Cloud Alibaba 致力于提供微服務(wù)開發(fā)的一站式解決方案,包含開發(fā)分布式應(yīng)用微服務(wù)的必需組件,方便開發(fā)者通過 Spring Cloud 編程模型輕松使用這些組件來開發(fā)分布式應(yīng)用服務(wù)。這些組件一部分以 SDK 的形式集成到代碼中,一部分以中間件的形式獨立運行,后者往往可以選擇托管版云產(chǎn)品,以降低開發(fā)者的工作量。比如阿里云微服務(wù)引擎 MSE 就提升了開箱即用的注冊配置中心 Nacos,以及云原生網(wǎng)關(guān)。
05
微服務(wù)架構(gòu)的挑戰(zhàn)
Aliware
微服務(wù)對單體架構(gòu)進行了拆分,不同模塊之間通過網(wǎng)絡(luò)進行通訊,本質(zhì)上來講,這并沒有降低系統(tǒng)的復(fù)雜度,反而讓系統(tǒng)復(fù)雜度大幅度提升,在管理難度上也為開發(fā)者提出了更高的挑戰(zhàn)。隨著微服務(wù)架構(gòu)的深入使用,波司登技術(shù)團隊遇到了2個難題:
性能問題定位困難 。 隨著業(yè)務(wù)規(guī)模的增長,對于每一個來自用戶的請求,鏈路變得越來越長,這也代表著應(yīng)用之間的調(diào)用關(guān)系變得越來越復(fù)雜。傳統(tǒng)的依賴于單機業(yè)務(wù)日志的監(jiān)控手段根本無從下手,這就需要建立全新的鏈路跟蹤機制,幫助開發(fā)者全面洞察系統(tǒng)運行狀態(tài),并在系統(tǒng)遇到異常的時候快速的定位和解決問題。這個挑戰(zhàn)相對比較容易解決,阿里云的 ARMS 應(yīng)用監(jiān)控提供了無侵入式方案實現(xiàn)微服務(wù)鏈路跟蹤,在易用性、功能性、穩(wěn)定性上都有突出的表現(xiàn)。波司登把部署在容器服務(wù) ACK 的微服務(wù)應(yīng)用一鍵接入 ARMS 應(yīng)用監(jiān)控后,接下來要做的事情就主要是熟練掌握工具,并配合 Promethues/Grafana 實現(xiàn)統(tǒng)一大盤,并利用報警平臺實現(xiàn)事件閉環(huán),ARMS 也通過開箱即用的方式在云上提供了相關(guān)工具。
應(yīng)用變更頻繁造成事故 。 為了適應(yīng)互聯(lián)網(wǎng)業(yè)務(wù)需求的不斷變化,應(yīng)用變更在大型微服務(wù)架構(gòu)中,是極為頻繁的工作。新應(yīng)用的上線、新版本的發(fā)布、新配置的推送、應(yīng)用擴容、應(yīng)用縮容,這些都屬于應(yīng)用變更的范疇。微服務(wù)架構(gòu)的復(fù)雜性以及業(yè)務(wù)的快速迭代,讓波司登的技術(shù)團隊在每次應(yīng)用變更中都疲憊不堪,因為絕大多數(shù)生產(chǎn)環(huán)境的事故都由應(yīng)用變更導致。這個難題不能簡單靠云產(chǎn)品來解決,需要技術(shù)團隊深入剖析每一次事故的根因,針對性的進行優(yōu)化,并建立一整套安全變更的行政機制,確保每一次變更都能讓團隊高枕無憂。第2個難題屬于微服務(wù)治理的范疇,微服務(wù)治理是微服務(wù)化深入的必經(jīng)之路,涵蓋流量治理、服務(wù)容錯、安全治理等多個領(lǐng)域,幫助更低成本、更穩(wěn)定、更高效地開發(fā),運維微服務(wù)應(yīng)用。在波司登的實戰(zhàn)經(jīng)驗中,上下線有損問題和安全變更問題造成的業(yè)務(wù)影響最大,波司登的技術(shù)團隊圍繞著這幾個問題進行了深入探索。
06
下線有損問題
Aliware
微服務(wù)化之后,有一個問題長期困擾著波司登的技術(shù)團隊:每次有應(yīng)用下線的時候,都會導致一部分前端用戶的請求失敗。應(yīng)用縮容和版本更新這2種情況都會產(chǎn)生應(yīng)用主動下線行為,這兩種情況對于波司登的業(yè)務(wù)系統(tǒng)都是每天都要執(zhí)行的日常工作。為了盡可能的保障用戶體驗,波司登最先考慮的是讓版本更新都在用戶量相對比較少的凌晨進行,以縮小問題的影響面,但這其實并不能太好的解決問題。一方面,為了提升資源利用率,應(yīng)用縮容基本上發(fā)生在白天;另一方面,凌晨進行版本變更加重了 IT 團隊的負擔,若是遇到了新版本的 bug,也不利于團隊進行保障,始終不是長久之計。因此還是要從根本上找到問題的原因,通過技術(shù)方式解決問題。 我們通過下面這個圖看一下微服務(wù)節(jié)點下線的正常流程

-
下線前,消費者根據(jù)負載均衡規(guī)則調(diào)用服務(wù)提供者,業(yè)務(wù)正常。
-
服務(wù)提供者節(jié)點 A 準備下線,先對其中的一個節(jié)點進行操作,首先是觸發(fā)停止 Java 進程信號。
-
節(jié)點停止過程中,服務(wù)提供者節(jié)點會向注冊中心發(fā)送服務(wù)節(jié)點注銷的動作。
-
服務(wù)注冊中心接收到服務(wù)提供者節(jié)點列表變更的信號后會,通知消費者服務(wù)提供者列表中的節(jié)點已下線。
-
服務(wù)消費者收到新的服務(wù)提供者節(jié)點列表后,會刷新客戶端的地址列表緩存,然后基于新的地址列表重新計算路由與負載均衡。
- 最終,服務(wù)消費者不再調(diào)用已經(jīng)下線的節(jié)點。
看似無懈可擊的邏輯,但在微服務(wù)系統(tǒng)的實際運行過程中,會存在一些微妙的差別。其本質(zhì)在于,從服務(wù)提供者確認下線,到服務(wù)消費者感知到服務(wù)提供者下線之間,存在時間差,這個時間差就是導致服務(wù)調(diào)用失敗的窗口期。比如 Spring Cloud 使用的 Ribbon 負載均衡默認的地址緩存刷新時間是 30 秒一次,那么意味著即使服務(wù)消費者實時地從注冊中心獲取到下線節(jié)點的信號在負載均衡的地址緩存沒有刷新前,依舊會有一段時間會將請求發(fā)送至老的服務(wù)提供者中。
了解到下線有損問題的本質(zhì)后,波司登技術(shù)團隊嘗試對微服務(wù)應(yīng)用進行了一些改造。對所有的微服務(wù)應(yīng)該都增加一個向外暴露的 /offline 接口,并把對這個接口的調(diào)用加入到 Kubernetes 的 Prestop 腳本中,這樣可以在 /offline 接口中加入服務(wù)注銷相關(guān)的邏輯。/offline 接口要實現(xiàn)的第一件事情是主動從注冊中心下線,這件事很好做,只需要一段代碼,但這并不夠,因為服務(wù)的消費者依然需要在一段時間后才能從注冊中心感知到這個事情。所以 /offline 接口還要實現(xiàn)主動通知服務(wù)消費方的邏輯,而這件事情在 Spring Cloud 框架中實現(xiàn)起來要復(fù)雜一些,因為沒有 channel 模型,服務(wù)提供方還不能真正實現(xiàn)主動通知服務(wù)消費方的需求,只能通過間接的方式實現(xiàn)。在請求的 Response Header 中帶上 ReadOnly 標簽,服務(wù)消費者收到 ReadOnly 標簽后,會主動刷新負載均衡緩存,保證不再有新的請求訪問下線過程中的服務(wù)提供者。這其中會存在少量的漏網(wǎng)之魚,也就說明,依然有少量請求會失敗。
此外,在下線的過程中,還有一部分請求屬于在途請求:服務(wù)提供方已經(jīng)收到了請求,但還沒有處理完成。要徹底解決下線有損的問題,需要服務(wù)提供者端等待所有在途請求處理都完成之后,再完成下線動作。具體等多久,這個時間是不確定的,所以漏網(wǎng)之魚始終存在,問題并沒有完全解決。
由于 /offline 接口的實現(xiàn)需要侵入代碼,而收效又有限,最終沒有能夠在波司登大面積推廣,這樣就只能繼續(xù)從業(yè)務(wù)上容忍下線有損問題了。
07
上線有損問題
Aliware
與下線有損問題相對應(yīng)的是上線有損問題,擴容、應(yīng)用新版本發(fā)布、Pod 重新調(diào)度都會產(chǎn)生應(yīng)用上線行為,相比下線有損問題,上線有損問題很容易被忽視,這是因為上線有損問題只有在高并發(fā)大流量的場景中才會暴露出來,其中最典型的場景就是高峰期的應(yīng)用彈性伸縮。 互聯(lián)網(wǎng)應(yīng)用的用戶流量存在明顯的波峰波谷,波司登也積極參與大促類營銷活動來提升品牌曝光度,高峰期的應(yīng)用彈性伸縮是一項常規(guī)技術(shù)手段。但波司登的技術(shù)團隊發(fā)現(xiàn)應(yīng)用彈性伸縮所達到的效果往往不及預(yù)期,其具體的表現(xiàn)是新擴容出來的應(yīng)用實例在啟動后會有3-5分鐘左右的性能瓶頸期,在這一段時間內(nèi),會造成部分用戶訪問延遲劇增,在極端大流量場景下甚至拖垮了整個應(yīng)用的性能,存在雪崩效應(yīng)的風險。 通過排查,波司登研發(fā)團隊找到了應(yīng)用上線后存在性能瓶頸期的多個原因:
異步連接資源阻塞 。在 jstack 日志中,發(fā)現(xiàn)不少線程阻塞在 taril/druid 等異步連接資源準備上,這是因為應(yīng)用實例啟動后,數(shù)據(jù)庫與 Redis 連接池中的連接未提前建立的情況下,就會接收來自上游的流量負載,從而導致大量線程阻塞在連接的建立上,在大流量場景下性能問題會更加突出。解決問題的思路是預(yù)建數(shù)據(jù)庫連接等異步建連邏輯,保證在業(yè)務(wù)流量進來之前,異步連接資源一切就緒。
ASMClassLoader 類加載器阻塞 。由于 ClassLoader 加載類的代碼其默認是同步類加載,在高并發(fā)場景下會有大量線程阻塞在 fastjson 的 ASMClassLoader 類加載器加載類的過程中,從而影響服務(wù)端性能,造成線程池滿等問題。解決的思路是類加載器被加載前開啟其并行類加載的能力。
JVM JIT 編譯引起 CPU 飆升 。當虛擬機發(fā)現(xiàn)某個方法或代碼塊運行特別頻繁時,就會把這些代碼認定為熱點代碼,為了提高熱點代碼的執(zhí)行效率,在運行時,虛擬機將會把這些代碼編譯成與本地平臺相關(guān)的機器碼,并進行各層次的優(yōu)化。這是 JVM 提升性能的重要技術(shù)手段,但JIT編譯本身會消耗大量計算資源,造成編譯期間的 CPU 使用率飆升。解決這個問題最好的方式是小流量預(yù)熱,讓 Java 應(yīng)用在啟動后可以先接收少部分流量,達到觸發(fā) JIT 編譯的條件,在編譯完成之后再接收正常的業(yè)務(wù)流量。
日志同步打印導致線程阻塞等其它問題 。 通過應(yīng)用代碼優(yōu)化實現(xiàn)無損上線,并不是一件簡單的事情,需要植入大量非功能性邏輯。特別在小流量預(yù)熱這項技術(shù)上,需要讓所有上游應(yīng)用感知到應(yīng)用上線的事件后,動態(tài)調(diào)整負載均衡規(guī)則,改造工作量極大。因此波司登的技術(shù)團隊并沒有自行從代碼層實現(xiàn)無損上線,而是往無代碼侵入的方向?qū)ふ覠o損上線的最優(yōu)解。 08
安全變更問題
Aliware
隨著波司登微服務(wù)架構(gòu)的不斷演進,系統(tǒng)支持的業(yè)務(wù)也越來越復(fù)雜,與此同時,業(yè)務(wù)的迭代速度也發(fā)生了翻天覆地的變化。在進行微服務(wù)改造之前,新版本發(fā)布的頻度是以月為單位,這跟現(xiàn)在每周有多個應(yīng)用需要發(fā)布新版本的情況完全不在一個數(shù)量級。在經(jīng)歷了多次新版本發(fā)布導致的生產(chǎn)事故之后,波司登的技術(shù)團隊吸取了之前的教訓,參考阿里巴巴的安全變更經(jīng)驗,提出了安全變更”可灰度、可監(jiān)控、可回滾“的原則,這就對波司登技術(shù)團隊的變更管理提出了更高的要求。特別是在灰度策略上,簡單的應(yīng)用滾動更新不能控制業(yè)務(wù)流量通往新版本的比例,不能夠滿足安全變更的要求,需要有更高階的灰度技術(shù)來支撐。 為了實現(xiàn)灰度過程中的路由可控,波司登最初采取的方式是通過物理隔離的方式構(gòu)建2套環(huán)境,每套環(huán)境都包含了全部的微服務(wù)應(yīng)用,以及 Message Queue、Redis 等其他中間件。通過前置的網(wǎng)關(guān)層實現(xiàn)流量路由,決定用戶的流量發(fā)送到正式環(huán)境還是灰度環(huán)境,路由的規(guī)則可以基于流量特征進行匹配,也可以設(shè)置為百分比。
這套架構(gòu)搭建完成之后,是能夠非常好的勝任安全變更原則的,每次有新版本發(fā)布的時候,都可以基于可控的流量進行小規(guī)模驗證。通過充分的驗證之后再決定是否放大進入新版本的流量比例,或者及時回滾。
但隨著物理隔離方案的推廣,其局限性也越來越明顯的暴露出來。首先這樣的架構(gòu)存在嚴重的資源浪費問題,雖然可以盡可能利用云計算的彈性能力適配流量規(guī)模,但也只是降低了一部分資源,不能從根本上解決資源浪費的問題。而且需要用到的中間件產(chǎn)品往往不能像微服務(wù)應(yīng)用一樣靈活的彈性伸縮。
此外,更重要的問題在于隔離方案需要整條業(yè)務(wù)線甚至全公司統(tǒng)一版本發(fā)布節(jié)奏,因為大家只有一套共享的灰度環(huán)境。微服務(wù)架構(gòu)的規(guī)模越大,團隊之間的分工會越明確,每個團隊所負責的微服務(wù)應(yīng)用在整個微服務(wù)架構(gòu)中所占的比重也就越小。這樣的方案在多團隊協(xié)同作戰(zhàn)的時候,極難協(xié)調(diào)多個團隊的版本發(fā)布節(jié)奏,實際上嚴重拖慢了業(yè)務(wù)系統(tǒng)的創(chuàng)新迭代速度。
因為物理隔離方案在實際生產(chǎn)中的局限性,業(yè)界更為推崇的是邏輯隔離方案。當需要對某一個微服務(wù)應(yīng)用發(fā)布版本的時候,可以獨立部署灰度版本,通過調(diào)用鏈路上的流量控制使得灰度流量能在灰度環(huán)境和正式環(huán)境間流轉(zhuǎn),實現(xiàn)灰度微服務(wù)應(yīng)用的正常運行,幫助業(yè)務(wù)方進行新功能驗證。邏輯隔離方案不需要做整套環(huán)境的冗余,大量節(jié)省了資源成本。更為關(guān)鍵的是,邏輯隔離方案可以讓不同的團隊各自決定自己的灰度節(jié)奏,并不需要所有團隊都在同一個容器期進行灰度驗證。這樣不僅可以大幅度提升業(yè)務(wù)系統(tǒng)創(chuàng)新迭代速度,還能更進一步降低變更所帶來的風險,因為職責分享以后,每個團隊都可以擁有更長的灰度窗口期,灰度驗證過程中遇到了問題也能更精確的定位到責任方。
然而邏輯隔離的技術(shù)實現(xiàn)極為復(fù)雜,物理隔離方案僅需要在網(wǎng)關(guān)層控制路由策略,而邏輯隔離需要每一個微服務(wù)應(yīng)用都必備識別灰度標識并動態(tài)控制路由策略的能力。在 Spring Cloud 框架下,微服務(wù)應(yīng)用之間相互調(diào)用的負載均衡機制由 Ribbon 實現(xiàn),實際上屬于應(yīng)用層 SDK 的能力范圍。動態(tài)控制路由策略相當于動態(tài)控制 Ribbon 的負載均衡策略,改造起來會有比較大的工作量。
邏輯隔離機制更為復(fù)雜的技術(shù)實現(xiàn)在于灰度標識的全鏈路透傳,也就是針對每一個用戶請求,如果在微服務(wù)應(yīng)用間流轉(zhuǎn)的過程中被打上了灰度標識,這個灰度標識就必須在接下來的鏈路中一直傳遞下去。比如上圖 B 服務(wù)的灰度服務(wù)在調(diào)用 C 服務(wù)的時候,因為 C 服務(wù)并沒有灰度版本,所以加到了 C 服務(wù)的穩(wěn)定版本,但接下來的 D 服務(wù)是同時存在穩(wěn)定版本和灰度版本的。這里就存在一個潛在的需求:凡是經(jīng)過了服務(wù) B 灰度服務(wù)的流量,都應(yīng)該發(fā)往服務(wù) D 的灰度版本。這個需求能夠?qū)崿F(xiàn)的必要條件,就是灰度標識的全鏈路透傳。
微服務(wù)應(yīng)用之間的灰度標識全鏈路透傳可以借助于 ARMS 等鏈路監(jiān)控工具而實現(xiàn),存在一定的代碼改造工作量。但更為復(fù)雜的是,如果鏈路中存在基于消息中間件的異步調(diào)用,就不能僅僅通過調(diào)整應(yīng)用層的負載均衡機制來控制路由策略了,需要對消息中間件的服務(wù)端和客戶端都進行適配,存在大量改造工作量。跟無損上線一樣,波司登的技術(shù)團隊也沒有急于求成對應(yīng)用層代碼進行大刀闊斧的改造,而是與阿里云團隊共同探討更優(yōu)雅的解決方案。
09
MSE 微服務(wù)治理方案
Aliware
微服務(wù)引擎 MSE 是阿里云面向業(yè)界主流微服務(wù)生態(tài)提供的一站式微服務(wù)平臺,包括注冊配置中心、云原生網(wǎng)關(guān)和微服務(wù)治理3款可以獨立輸出的產(chǎn)品。對于注冊配置中心和云原生網(wǎng)關(guān),波司登已經(jīng)比較熟悉了,分別為微服務(wù)架構(gòu)提供了 Nacos 以及 Kubernetes Ingress 服務(wù)。關(guān)于第3款產(chǎn)品微服務(wù)治理,波司登的技術(shù)團隊有過深入的研究,對于解決安全變更領(lǐng)域的多個難題都能帶來幫助,但對于微服務(wù)應(yīng)用全面接入 MSE 微服務(wù)治理,波司登還是存在一些顧慮。
主要的顧慮點集中在技術(shù)改造復(fù)雜度、侵入性、穩(wěn)定性等方面,波司登的技術(shù)團隊與阿里云的專家團隊經(jīng)過深入的溝通,對所有潛在風險點逐一進行了評估。經(jīng)過大量的預(yù)研后,波司登決定將微服務(wù)應(yīng)用全面接入MSE微服務(wù)治理。這個方案除了在功能層面能夠滿足波司登微服務(wù)治理的需求之外,波司登的技術(shù)團隊更看中的是這幾個方面的特性:
無侵入。 MSE 微服務(wù)治理能力基于 Java Agent 字節(jié)碼增強的技術(shù)實現(xiàn),無縫支持市面上近5年的所有 Spring Cloud 的版本。研發(fā)團隊不用改一行代碼就可以使用,甚至在研發(fā)階段都不需要考慮應(yīng)用部署的時候是否接入 MSE 微服務(wù)治理,讓研發(fā)團隊更聚焦于業(yè)務(wù)的創(chuàng)新。這是一個非常重要的特性,體現(xiàn)了這套方案的開放度,也能確保方案不會有廠商鎖定問題。
接入簡單。 用戶只需在阿里云容器的應(yīng)用市場安裝 pilot 組件,就可以通過 MSE 控制臺對一個命名空間的所有 Java 應(yīng)用開啟治理功能,這個時候 pilot 組件會自動為 Java 應(yīng)用所在的 Pod 注入 Agent 。當然,更通用的方式是通過 Kubernetes 的聲明式描述,來控制每個應(yīng)用是否開啟治理功能,也就是對 Pod 的 yaml 文件加上一行注解,這樣能更方便的和 CI/CD 工具集成。當然關(guān)閉服務(wù)治理功能也是非常容易的,只需在控制臺關(guān)閉服務(wù)治理,或者修改 yaml 文件上的注解就行,不需要改變業(yè)務(wù)的現(xiàn)有架構(gòu),根據(jù)需要隨啟隨停。
高穩(wěn)定性。 同時服務(wù)于阿里集巴的內(nèi)部應(yīng)該以及多個外部客戶,經(jīng)過了大規(guī)模實戰(zhàn)驗證。
可觀測能力。 提供完整的流量可視化視圖,支持全局看板、網(wǎng)關(guān)實例監(jiān)控、日志檢索、業(yè)務(wù) TOP 榜、日志投遞、以及報警管理等功能。能夠幫助用戶直接的了解到微服務(wù)治理能力開啟后產(chǎn)生的效果,更全面的了解微服務(wù)應(yīng)用的運行狀態(tài)。
支持混合云場景。 不論是在線下 IDC,還是其他云上部署的微服務(wù)系統(tǒng),只要網(wǎng)絡(luò)可以通,也能夠享受到治理能力的增強,用法保持一致。
擁抱云原生。 與 Kubernetes 體系完美集成,無損上下線使得應(yīng)用在彈性伸縮的過程中保持流量無損,通過 Jenkins 構(gòu)建 CI/CD 實現(xiàn)在 Kubernetes 環(huán)境下的金絲雀發(fā)布,基于 Ingress 實現(xiàn)全鏈路灰度等。
10
無損下線
Aliware
MSE 實現(xiàn)無損下線的原理很簡單,流程如下:
當一個微服務(wù)應(yīng)用實例接收到下線指令后,紅色字段標識的3個步驟由 Agent 自動實現(xiàn)
從注冊中心下線。 這一步執(zhí)行完之后,服務(wù)的所有消費者有機會從注冊中心感知到下線行為,但在 Spring Cloud 體系中,這個感知存在時間差,并不能立即通知所有消費者,所以我們不能單純依賴這個步驟實現(xiàn)無損下線。
主動通知所有消費者。 這是最為關(guān)鍵的一步,Agent 繞過注冊中心,直接給所有消費者發(fā)送了實例下線的通知,這樣消費方能夠立即感知到下線行為。
消息者更新負載均衡。 收到實例下線通知后,服務(wù)的消費方將下線的實例從負載均衡實例列表中移除,從而不再發(fā)請求到下線的實例。這幾個步驟都完成以后,收到下線指令的應(yīng)用實例才會在處理完所有在途請求的情況下,進入真正的下線狀態(tài)。所以整個過程不會有任何一次服務(wù)請求失敗的情況發(fā)生。這項技術(shù)不需要修改任何一行代碼,就能在版本更新或應(yīng)用縮容的時候提升用戶體驗,增加微服務(wù)系統(tǒng)的穩(wěn)定性。
如果一個微服務(wù)應(yīng)用處在鏈路的入口位置,通過 Ingress 暴露給用戶,這個時候并不存在掛上了 Agent 的服務(wù)消費者應(yīng)用,無損下線機制還能正常工作嗎?答案是肯定的,如果 Ingress 這一層是由 MSE 云原生網(wǎng)關(guān)實現(xiàn)的,所有的適配工作都已經(jīng)完成,無損下線機制依然可以完美運行。 11
無損上線
Aliware
MSE 實現(xiàn)無損上線也是基于類似的原理:
-
微服務(wù)消費者可以快速感知微服務(wù)提供方的上下線事件
- Agent 可以動態(tài)更新微服務(wù)消費方的負載均衡規(guī)則
因此,用戶可以為每一個微服務(wù)消費者配置一定時長的預(yù)熱窗口期,比如2分鐘。在這一段時間內(nèi),如果感知服務(wù)提供方的實例新上線,就在窗口期通過小流量對新上線的實例進行預(yù)熱,并逐步增量流量規(guī)模,直到窗口期結(jié)束后恢復(fù)正常的流量比例,這樣就可以規(guī)避 Java 應(yīng)用啟動初期所存在的性能問題。
完整的流程如下:
不論是無損上線還是無損下線,都通過從 MSE 的控制臺清晰的觀察到微服務(wù)治理帶來的效果。

全鏈路流量治理
Aliware
通過 MSE 微服務(wù)治理,長期困擾波司登的安全變更問題得到了解決,因為波司登一直在追求的邏輯隔離灰度方案可以通過 Agent 技術(shù)輕松實現(xiàn)。為了實現(xiàn)邏輯隔離灰度,可以先從金絲雀發(fā)布開始入手,金絲雀發(fā)布在業(yè)界有廣泛的使用,是應(yīng)用版本更新的常用灰度手段。金絲雀發(fā)布會對流量進行比例分割,一開始為新版本的實例分配較小比例的流量,經(jīng)過一段時間的運行,確認新版本運行正常后再逐步提高所分配流量的比例,直到最終全量切流。通過這種方式做發(fā)布可以在新版本出現(xiàn)問題時控制影響面,提高系統(tǒng)的穩(wěn)定性。 金絲雀發(fā)布通常通過流量染色和版本打標來實現(xiàn)。在 MSE 的實現(xiàn)中,流量染色可以通過識別流量特征而實現(xiàn),在下圖的例子中,可以通過 HTTP Header 里面的具體字段來決定一個請求是否進行灰度染色。而版本打標是利用 Kubernetes 的聲明式部署實現(xiàn)的,通過在 Pod 上添加 Annotation ,可以讓對應(yīng)的版本打上灰度標識。這樣就可以限制只有被染過色的流量才會進入打上了灰度標識的版本,從而實現(xiàn)新版本業(yè)務(wù)的小規(guī)模驗證,一旦發(fā)現(xiàn)新版本存在任何問題,可以及時回滾,把對業(yè)務(wù)的影響降至最低。
金絲雀發(fā)布最終會演變成全鏈路流量治理能力,從而真正實現(xiàn)基于邏輯隔離機制的高階灰度方案。對于穿梭在微服務(wù)鏈路上的流量,一旦被染色,就能將染色信息傳遞到整條鏈路。這個機制和泳道非常類似,微服務(wù)在同一時間點可能存在多個并存的業(yè)務(wù)版本,每條泳道象征著一個業(yè)務(wù)版本,只有經(jīng)過染色的流量,才會進入到對應(yīng)泳道中。
波司登經(jīng)過半年時間的實戰(zhàn)探索,在 MSE 微服務(wù)治理的幫助下,最終駕馭了大規(guī)模微服務(wù)架構(gòu)的全鏈路流量治理能力,并形成了成熟的流程機制,通過全鏈路流量治理對每一次應(yīng)用變更進行充分的灰度驗證。有了這項技術(shù)之后,每個團隊都可以靈活的決定應(yīng)用變更的時間周期,但對于安全變更的要求變得更高了,一旦造成了生產(chǎn)事故,在行政上會有更嚴厲處罰措施。因此需要每個團隊在實施應(yīng)用變更的時候,都通過全鏈路流量治理確保穩(wěn)定性,這樣即使新版本存在漏洞,對于整體業(yè)務(wù)的影響也能控制在極低的范圍內(nèi)。這項技術(shù)被各團隊廣泛采納后,
波司登的業(yè)務(wù)迭代頻率實現(xiàn)了2倍以上的提升,因為應(yīng)用變更導致的生產(chǎn)事故降低了 70% 以上。
13
全鏈路穩(wěn)定性治理
Aliware
另一個被波司登廣泛使用的微服務(wù)治理能力是全鏈路穩(wěn)定性治理,對于波司登這樣需要頻繁舉辦線上運營活動的企業(yè),全鏈路穩(wěn)定性治理是非常重要的技術(shù)。MSE 提供的全鏈路穩(wěn)定性治理,在流量防護方面形成可拓展閉環(huán),能夠通過故障識別模型發(fā)現(xiàn)不同層次的問題,如接口層的狀態(tài)碼與異常類型、操作系統(tǒng)層的指標異常。在識別出問題后,發(fā)出異常告警,方便用戶進行針對性的流量治理,如進行自適應(yīng)限流防護或場景化限流防護;防護規(guī)則設(shè)置后,系統(tǒng)便按照預(yù)設(shè)的閾值與防護手段保護系統(tǒng),而系統(tǒng)防護的效果可通過監(jiān)控查看,另一方面,也可通過監(jiān)控反向?qū)徱暳髁糠雷o規(guī)則設(shè)置的合理性,及時調(diào)整。
對于防護策略以及防護規(guī)則的設(shè)定,波登司主要通過全鏈路壓測獲得參考。波司登通過阿里云 PTS 模擬用戶流量,對系統(tǒng)進行了多次全鏈路壓測。在壓測的過程中不斷優(yōu)化微服務(wù)架構(gòu)各個環(huán)境的容量配比,確定系統(tǒng)在真實業(yè)務(wù)中表現(xiàn)出來的系統(tǒng)上限,同時也確定在大流量場景下需要使用到的流量防護策略。為了更進一步提升微服務(wù)系統(tǒng)在高并發(fā)大流量場景的性能,并提升資源利用率,波司登還充分利用了 ACK 集群的彈性伸縮能力,在業(yè)務(wù)高峰期讓應(yīng)用和集群資源同時實現(xiàn)自動水平擴擴展,并在業(yè)務(wù)高峰期自動回收資源。
除了在業(yè)界廣泛運用的單機流控手段(包括并發(fā)控制、自適應(yīng)防護、熔斷、主動降級、熱點防護等一系列技術(shù))和網(wǎng)關(guān)流控手段之外,波司登還深入使用了MSE提供的數(shù)據(jù)庫治理能力,特別是基于 SQL 的流控、降級、容錯,避免嚴重的慢 SQL 發(fā)生后拖垮整個數(shù)據(jù)庫,對線上業(yè)務(wù)產(chǎn)生阻斷性的風險。
在全鏈路穩(wěn)定性治理和彈性伸縮的幫助下,再加上頁面靜態(tài)化、請求攔截、數(shù)據(jù)隔離、異步處理等常規(guī)技術(shù)手段,波司登已經(jīng)建立起在秒殺業(yè)務(wù)場景中支撐百萬級并發(fā)量的技術(shù)能力,并確保雙11活動過程系統(tǒng)的穩(wěn)定運行。
14
總結(jié)
Aliware
技術(shù)能力的不斷進步,幫助波司登使用數(shù)字化手段對業(yè)務(wù)進行不斷創(chuàng)新,并取得了一系列重要的戰(zhàn)果。數(shù)字化能力的提升也直接體現(xiàn)在銷量與利潤上,波司登在羽絨服的銷售額和銷售量上都登上了全球第一,連續(xù)5年實現(xiàn)了營收與利潤的雙位數(shù)增長。波司登的技術(shù)團隊在云原生微服務(wù)治理方面的不斷探索,讓他們在超大規(guī)模微服務(wù)架構(gòu)領(lǐng)域沉淀寶貴經(jīng)驗,但這只是支撐業(yè)務(wù)高速發(fā)展所經(jīng)歷的多項技術(shù)變革中的一個重要組成部分。波司登會繼續(xù)擁抱云計算,通過更先進、更高效的技術(shù),更數(shù)字化的運營方式,引領(lǐng)服飾行業(yè)激發(fā)創(chuàng)新活力,與各行各業(yè)的時代變革者共同成長。
推薦閱讀:
掘地三尺搞定 Redis 與 MySQL 數(shù)據(jù)一致性問題
后端思維篇:如何應(yīng)用設(shè)計模式優(yōu)化代碼
歡迎關(guān)注微信公眾號: 互聯(lián)網(wǎng)全棧架構(gòu) ,收取更多有價值的信息。
