應用釋出、服務更新一直是一個讓開發和運維同學既興奮又擔心的事情。
興奮的是有新功能上線,自己的産品可以對使用者提供更多的能力和價值;擔心的是上線的過程會不會出現意外情況影響業務的穩定性。确實,在應用釋出和服務更新時,線上問題出現的可能性更高,本文我們将結合 Serverless 應用引擎(以下簡稱 SAE)就 Serverless 架構下,讨論如何保障上線過程中服務的優雅下線。
在平時的釋出過程中,我們是否遇到過以下問題:
- 釋出過程中,出現正在執行的請求被中斷?
- 下遊服務節點已經下線,上遊依然繼續調用已經下線的節點導緻請求報錯,進而導緻業務異常?
- 釋出過程造成資料不一緻,需要對髒資料進行修複。
有時候,我們把發版安排在淩晨兩三點,趕在業務流量比較小的時候,心驚膽顫、睡眠不足、苦不可言。那如何解決上面的問題,如何保證應用釋出過程穩定、高效,保證業務無損呢?首先,我們來梳理下造成這些問題的原因。
場景分析

這個圖描述了我們使用微服務架構開發應用的一個常見的場景,先看下這個場景的服務調用關系:
- 服務 B、C 把服務注冊到服務注冊中心,服務 A、B 從注冊中心發現依賴的服務。
- 業務流量從負載均衡路由到服務 A,在 SLB 上配置服務 A 執行個體的健康檢查,當服務 A 有執行個體停機的時候,相應的執行個體從 SLB 摘掉;服務 A 調用服務 B,服務B再調用服務C。
從圖中,可以看到有兩類流量,南北向流量(即通過 SLB 轉發到後端伺服器的業務流量,如業務流量->SLB->A的調用鍊路)和東西向流量(借助于服務注冊中心服務發現調用的流量,如服務A->服務B的調用鍊路)
針對這兩類流量我們分别進行分析。先來分析下在這種架構下南北向流量存在的問題,當服務 A 釋出的時候,服務A1 執行個體停機後,SLB 根據健康檢查探測到執行個體 A1 下線,然後把執行個體從 SLB 摘掉,執行個體 A1 依賴 SLB 的健康檢查從 SLB 上摘掉,一般需要幾秒到十幾秒的時間,在這個過程中,如果 SLB 有持續的流量打入,就會造成一些請求繼續路由到執行個體 A1,導緻請求失敗。
那如何保證經過SLB的業務流量不報錯?我們看下 SAE 是如何做到的。
南北向流量優雅下線方案
上面提到過,請求失敗的原因在于後端服務執行個體先停止掉,然後才從 SLB 摘掉,那我們是不是可以先從 SLB 摘掉服務執行個體,然後在對執行個體進行更新呢?
按照這個思路,SAE 基于 K8s Service 的能力給出了一種方案,當使用者在通過 SAE 為應用綁定 SLB 時,SAE 會在叢集中建立一個 Service 資源,并把應用的執行個體和 Service 關聯,CCM 元件會負責 SLB 的購買、SLB 虛拟伺服器組的建立,并且把應用執行個體關聯的 ENI 網卡添加到虛拟伺服器組中,進而使用者可以通過 SLB 來通路應用執行個體;當應用釋出時,CCM 元件會先把執行個體對應的 ENI 從虛拟伺服器組中摘除,然後再對執行個體進行更新,進而保證了流量不丢失。
東西向流量優雅下線方案
在讨論完南北向流量的解決方案後,我們再看下東西向流量, 傳統的釋出流程中,服務提供者停止再啟動,服務消費者感覺到服務提供者節點停止的流程如下:
- 服務釋出前,消費者根據負載均衡規則調用服務提供者,業務正常。
- 服務提供者 B 需要釋出新版本,先對其中的一個節點進行操作,首先是停止 Java 程序。
- 服務停止過程,又分為主動登出和被動登出,主動登出是準實時的,被動登出的時間由不同的注冊中心決定,最差的情況會需要 1 分鐘。
- 如果應用是正常停止,Spring Cloud 和 Dubbo 架構的 Shutdown Hook 能正常被執行,這一步的耗時可以忽略不計。
- 如果應用是非正常停止,比如直接使用 kill -9 停止,或者 Docker 鏡像建構的時候 Java 應用不是 1 号程序且沒有把 kill 信号傳遞給應用。那麼服務提供者不會主動去登出服務節點,而是在超過一段時間後由于心跳逾時而被動地被注冊中心摘除。
- 服務注冊中心通知消費者,其中的一個服務提供者節點已下線。包含推送和輪詢兩種方式,推送可以認為是準實時的,輪詢的耗時由服務消費者輪詢間隔決定,最差的情況下需要 1 分鐘。
- 服務消費者重新整理服務清單,感覺到服務提供者已經下線了一個節點,這一步對于 Dubbo 架構來說不存在,但是 Spring Cloud 的負載均衡元件 Ribbon 預設的重新整理時間是 30 秒 ,最差情況下需要耗時 30 秒。
- 服務消費者不再調用已經下線的節點。
從第 2 步到第 6 步的過程中,Eureka 在最差的情況下需要耗時 2 分鐘,Nacos 在最差的情況下需要耗時 50 秒。在這段時間内,請求都有可能出現問題,是以釋出時會出現各種報錯。
經過上面的分析,我們看,在傳統釋出流程中,用戶端有一個服務調用報錯期,原因就是用戶端沒有及時感覺到服務端下線的執行個體造成的,這種情況主要是因為服務提供者借助注冊中心通知消費者來更新服務提供者清單造成的,那能不能繞過注冊中心,服務提供者直接通知服務消費者呢?答案是肯定的,SAE 主要做了兩件事情。
- 服務提供者應用在釋出前後主動向注冊中心登出應用,并将應用标記為已下線的狀态;将原來的停止程序階段 登出服務變成了 prestop 階段登出服務。
- 在接收到服務消費者請求時,首先會正常處理本次調用,并通知服務消費者此節點已下線,服務消費者會立即從調用清單删除此節點;在這之後,服務消費者不再調用已經下線的節點。這是将原來的依賴于 注冊中心推送,變成了服務提供者直接通知消費者從調用清單中摘除自己。
通過上面這個方案,就使得下線感覺的時間大大減短,從原來的分鐘級别做到準實時,確定您的應用在下線時能做到業務無損。
分批釋出和灰階釋出
上面介紹的是 SAE 在處理優雅下線方面的一些能力,在應用釋出的過程中,隻有執行個體的優雅下線是不夠的,需要有一套配套的釋出政策,保證我們新業務是可用的,SAE 提供了分批釋出和灰階釋出的能力,可以使得應用的釋出過程更加省心省力;
我們先介紹下灰階釋出,某應用包含10個應用執行個體,每個應用執行個體的部署版本為Ver.1版本,現需将每個應用執行個體更新為Ver.2版本。
從圖中可以看出,在釋出的過程中先灰階2台執行個體,在确認業務正常後,再分批釋出剩餘的執行個體,釋出的過程中始終有執行個體處于運作狀态,執行個體更新過程中依照上面的方案,每個執行個體都有優雅下線的過程,這就保證了業務無損。
再來看下分批釋出,分批釋出支援手動、自動分批;還是上面的10個應用執行個體,假設将所有應用執行個體分3批進行部署,根據分批釋出政策,該釋出流程如圖所示,就不再具體介紹了。
如果您想體驗 Serverless 架構下在微服務應用的優雅下線、分批釋出和灰階釋出方面的能力,歡迎您登陸 SAE 的
控制台 >>【更多精彩】
1.中間件爆款一折起,還有阿裡巴巴十年最佳實踐深度解密,點選馬上了解:
https://www.aliyun.com/activity/daily/commercial?spm=5176.20960838.0.0.6a54305etoEn4D2.【填問卷領淘公仔】點選馬上填寫問卷:
https://survey.aliyun.com/apps/zhiliao/YmW95Gk8bU【加入行業實戰交流釘釘群】
阿裡雲專門成立了“網際網路架構更新實戰課”釘釘群,每周邀請一位阿裡雲專家在群内進行行業最佳實踐直播,每天分享行業前沿幹貨,釘釘掃碼馬上加入。