攜程酒店 AWS 實踐

一、背景


隨着攜程海外酒店業務的發展,遍佈全球的海外供應商與攜程總部 IDC 之間的數據傳輸量快速增長。技術上,這種日益增長的數據量對跨境網絡專線的帶寬、延遲等提出了更高的要求;業務上,由於當前有限的跨境網絡專線資源對業務處理效率及用戶體驗也造成了一定的影響;成本上,跨境網絡專線作爲一種昂貴的資源,通過單純的專線擴容又會給 IT 成本造成巨大壓力。所以我們開始思考是否可以通過公有云結合酒店直連的業務特性來解決日益增長的帶寬壓力和供應商接口延遲的問題。

酒店直連繫統主要是使用自動化接口實現供應商或集團與攜程之間的系統對接,實現靜態信息、動態信息、訂單功能等都通過系統的方式流轉交互。目前攜程大量海外酒店業務是通過酒店直連繫統對接。

本文將主要從攜程酒店直連服務遷移部署至 AWS 過程中所進行的應用架構調整及雲原生改造,使用 AWS 後取得的技術和業務收益,在部署過程中對 EKS(Amazon Elastic Kubernates Service)、DNS 查詢延時和跨 AZ 流量降低所做的成本優化等幾方面進行詳細介紹。

二、痛點

攜程酒店海外直連對接了上千家海外供應商,所有的接口訪問都通過代理出去(見圖 1),由於酒店直連的業務特性,當一個用戶請求過來時會根據人數、國籍、會員非會員等裂變成多個請求,最多的時候可能一個請求會裂變成數十個請求,而且請求報文十分巨大(通常爲幾十 Kb 到上百 Kb 不等),雖然我們可能只需要返回報文中的一小部分信息,但是因爲目前架構的限制只能將所有報文全部請求回來再處理,這無疑浪費了大量的帶寬。

圖 1

同時因爲供應商遍佈全球,所有的請求 / 響應都需要經過集團的代理出口,導致了部分供應商接口響應受到物理距離的影響延遲變高了,會降低用戶的體驗。

三、雲服務選擇及初步方案

本次核心目標之一是爲了提高對接全球供應商的網絡傳輸能力和延時改進,提升用戶體驗,必須選擇一個在全球有廣泛資源分佈的雲廠商幫助攜程儘量靠近供應商訪問數據。經過與多個公有云廠商的多輪交流,綜合考慮各廠商技術水平、服務能力、成本價格等多方面因素,我們認爲 AWS 無論是在全球覆蓋及網絡能力(見圖 2)(AWS 在全球分佈的 25 個區域和 80 個可用區提供廣泛的服務能力,同時數據中心通過其骨幹網互聯,提升了未來不同數據中心的數據互訪能力),雲服務的先進性和成熟度、現場團隊的服務能力、響應時間、專業水平都具有明顯的優勢,最終我們選擇 AWS 作爲資源部署的雲廠商合作伙伴。

圖 2

爲了更好地與雲上資源使用集成,我們採用 IDC 的容器化部署方案,最終考慮到託管容器平臺的高可用性設計及 SLA 保證,及對社區的兼容性,使用 AWS 託管容器平臺 EKS 作爲部署的平臺。

資源方面我們對服務進行改造後,大量使用競價實例作爲 EKS 工作節點,大幅降低成本並提高效率。

同時利用公有云的網絡和平臺優勢,將原本部署在攜程總部 IDC 的相應業務服務部署到離供應商距離更近的海外公有云站點,實現攜程與海外供應商之間高可靠、低延遲的網絡直連,並將部分數據預處理邏輯剝離出來前置部署到海外公有云上,實現僅將經過處理的有價值的數據(而非原始、全量的裸數據)壓縮後再傳輸到攜程總部數據中心,進而達到降低對跨境網絡專線的壓力、提升業務數據處理效率、降低成本、優化用戶體驗等目標。

四、酒店直連上雲經驗

4.1 雲業務應用的雲原生改造

爲了充分的使用雲服務帶來的便利和成本優化,經過調研分析,我們如果直接將應用遷移至公有云上,雖然業務上會產生相應的價值,但成本會相對較高,因此我們對酒店直連服務進行了相應的雲原生架構優化,相關的主要調整如下:

1 )訪問供應商模塊上雲

要節省帶寬需要減少通過從代理出去的請求同時減少每個請求的報文大小。我們的做法是將請求拆分的邏輯搬到 AWS 上,這樣每次一個用戶請求過來通過代理出去只有一次請求 / 響應。同時我們在 AWS 上將供應商返回的報文中無用屬性剔除,然後再根據業務屬性合併相關節點最後再壓縮返回,這樣就達到了縮減報文大小的目的 (見圖 3)。從目前運行的數據上看,整個代理的帶寬流量只用到了之前的 30%~40%。

圖 3

公有云廠商普遍採用按流量收費的價格策略,在設計網絡出入站網絡訪問的技術方案過程中,默認情況下會使用 AWS NAT 網關,這樣網絡流量費用相對較高。考慮到酒店直連請求有個特性,通常情況下請求報文不到 1K,而響應報文平均有 10k 到 100K,利用這個特點,我們在 AWS 上採用了基於 EKS 自建 Squid 代理方案(見圖 4),這樣只有出站的請求報文會產生流量費用,而大量入站的響應報文不收費,從而大大降低 AWS 上產生的網絡流量費用。

圖 4

2)降低網絡延遲,利用 AWS 全球數據中心對供應商就近訪問

很多海外的供應商服務部署在全球各地,而我們所有的海外訪問都統一從代理出去,這樣一些服務器部署較遠的供應商因爲物理距離上的原因導致網絡延遲很高。通過 AWS 的在全球各地的數據中心,我們可以將服務就近部署在供應商機房附近,同時利用 AWS 的骨幹網絡降低各數據中心到代理所在地附近的 AWS 數據中心的延遲,最後通過專線連接該 AWS 數據中心與攜程 IDC(見圖 5),整個過程對那些因物理距離對網絡延遲影響較大的供應商性能提升較明顯,最多可降低 50% 的響應時間。

圖 5

4.2 持續的架構改造和性能及成本優化

在目前的方案中,我們爲了上雲單獨開發了一套全新的應用,這樣帶來的問題就是,當有業務變更時我們同時需要調整攜程 IDC 和 AWS 上部署的兩個應用,提高了系統維護成本。主要原因是原應用中大量依賴攜程的基礎組件,本次上雲嘗試使用的是完全獨立的賬號和 VPC 網絡,如果在雲上同樣部署一套不太現實,一是成本太大,二是一些敏感數據不能放在在雲端存儲,所以後續我們會對適配器架構再進行優化,在不依賴攜程基礎組件的情況下複用一套應用以適應不同的雲環境。

業務上線後爲了驗證未來更大規模的負載上雲的可能性,我們同時也在對性能,成本,高可用性方面做持續不斷的優化

4.2.1 利用雲彈性伸縮能力

以計算資源成本爲例:計算實例成本 = 實例運行時長 * 實例價格。如果只是簡單粗暴把本地機房的運行模式套用到雲上計算,雲服務計算資源的費用是高於本地機房的。所以我們需要充分利用雲上按需收費的特性,減少閒置資源成本。實例的運行時長和 Kubernetes 集羣內的服務數量,以及分配給這些服務的計算資源成正比,同時服務的數量又是和流量成正比。

酒店直連業務場景存在不可預測的業務流量,比如臨近節假日頒佈的旅遊政策,或者營銷直播活動。雲原生的彈性特性很好地利用合理的資源應對突發的流量。

Kubernetes 的 HPA 彈性架構會實時採集集羣整體的負載指標,判斷是否滿足彈性伸縮條件和執行 pod 的伸縮。僅僅是 pod 的伸縮還不夠,我們還需要在集羣中使用 Cluster Autoscaler 組件,監控集羣中由於資源分配不足無法被正常調度的 pod,自動從雲平臺的實例池中申請增加節點,同時在流量下降的時候,Cluster Autoscaler 組件也會檢測集羣中資源利用率較低的節點,將其中的 pod 調度到其他可用節點上,回收這部分閒置節點。

彈性伸縮案例

雲原生的彈性特性不僅幫助減少資源使用成本,也提高服務對基礎架構故障的容錯率,在基礎設施部分可用區中斷不可用期間,其他可用區域會增加相應數量的節點繼續保持整個集羣的可用。

Kubernetes 支持對 pod 容器所需的 CPU 和內存調整,找到一個合理的配額以合理的成本達到最佳的性能。所以我們在服務上雲前會做一些接近真實環境的負載測試,觀察業務流量的變化對集羣性能的影響(業務週期性高峯和低峯的資源使用率,服務的資源瓶頸,合適的餘量資源 buffer 應對尖刺流量等等)。既不會因爲實際利用率過高導致穩定性問題,比如 OOM 或者頻繁的 CPU throttling,也不會因爲過低浪費資源(畢竟,即使你的應用只使用了實例的 1%,也要支付該實例 100% 的費用)。

4.2.2 採用公有云競價實例

某些雲平臺會把一些閒置計算資源作爲競價實例,以比按需實例更低的定價出租,顧名思義競價實例的最終費用是按市場供需出價決定的。按照我們實際使用的體驗,如果不是特別熱門的機型定價基本在按需實例費用的 10-30% 左右。低價的競價實例自然有它的限制,雲平臺會可能會調整競價實例池的資源比例回收部分實例,一般回收的概率根據統計通常 < 3%, 同時在回收前會提前 2 分鐘通知到這些實例。我們通過 AWS 提供的 Terminal handler 組件在收到回收通知後提前把容器調度到其他可用的實例上,減少了資源回收對服務的影響。下圖是某雲對競價實例的資源池劃分,我們可以看到,即使相同的實例資源,在不同的可用區也是獨立的資源池。

圖 6

爲了能最大限度減少競價實例的中斷影響,包括實例在多可用區的再平衡影響,我們在通過 ASG(AWS auto scaling Group 彈性擴展組)選擇不同實例類型的情況下還將不同的實例資源池獨立使用 ASG 進行管理,這樣保證了資源的最大利用效率。

圖 7

攜程酒店直連使用按需實例和競價實例的混合部署,保證低成本和高可用。一些系統關鍵組件(比如 Cluster Autoscaler),中斷就會丟失數據的有狀態服務(比如 Prometheus)運行在按需實例。而對錯誤容忍度高,使用靈活無狀態的業務應用運行在競價實例上。通過 kubernetes 的節點親和性控制不同類型的服務調度到對應類型標籤的實例上。(見圖 8)

圖 8

通過 kubernates 原生的 HPA 和 ClusterAutoscaler 組件結合 AWS ASG 及競價資源的充分利用,可以將成本降低 50%-80%。

4.2.3 DNS 解析性能優化

當服務規模逐漸增大的時候,我們發現服務間的調用延時明顯上升,平均達到 1.5S,高峯達到 2.5 秒,經過分析發現,主要是因爲 DNS 解析負載過高造成的性能解析瓶頸,最終我們採用社區比較主流的 localdns 方式,對熱點解析域名做本地緩存,來降低對核心 DNS 頻繁的解析請求從而提高性能:

圖 9

如圖 9 所示,在每個 Node 部署基於 DaemonSet 的 NodeLocal DNSCache,通過 Node LocalDNS 緩解 CoreDNS 服務的 DNS 查詢壓力,LocalDNS Cache 會監聽所在的 node 上每個 Client Pod 的 DNS 解析請求,通過本地的解析行爲配置,Local DNS Cache 會嘗試先通過緩存解析請求,如果未命中則去 CoreDNS 查詢解析結果並緩存爲下一次本地解析請求使用。

如下圖,通過使用 LocalDNS 方案我們將高峯的延時從 2.5S 降低到 300ms,縮短了 80% 的響應時間:

未使用 LocalDNS 前,平均響應在 1.5-2.5S。

未優化前

使用 LocalDNS 方案後,響應請求降低到 300-400ms,延時優化了 80%。

優化後

4.2.4 公有云跨可用區流量優化

在使用競價實例對資源進行大幅優化後,我們注意到跨可用區的流量在服務大幅擴展後佔比非常高(60%),這是因爲在服務之間調用時,我們將服務單元部署到不同可用區,最大限度提高服務的可用性,同時帶來的問題是服務間大量的流量交互帶來了跨可用區的流量費用(見圖 10)。

圖 10

但是爲了整個系統的高可用性,我們並不想將服務部署在單可用區,降低服務 SLA。我們需要降低跨可用區流量的同時保證服務的高可用性。

經過不同的方案調研最終我們使用 AWS NLB 來暴露服務,通過 NLB 的 disable cross-az 功能,對同可用區的上下游服務進行流量可用區管控。同時使用之前提到的 local dns 組件,將上游服務訪問 NLB 不同可用區的域名解析進行固化,保證了上下游的服務流量只能在可用區內部進行互通。改造後如下圖:

圖 11

後段服務因爲會通過 K8s 的 Kube-proxy 進行轉發造成跨可用區跨節點,我們選擇使用 externalTrafficPolicy 本地策略,將轉發流量固化在本地節點的服務上,但是同時本地轉發策略也帶來了一些問題(見圖 12):

圖 12

如上圖所示,本地轉發策略可能因爲後端服務分佈不均衡導致了流量黑洞和服務負載的不均衡,所以在這個基礎上,我們利用 EKS 彈性擴展組策略對底層節點資源均衡分佈到不同的可用區,同時利用 K8s 反親和性策略,將服務儘量分佈到不同可用區的節點上,最大程度的保證了流量的均衡性,同時保證了服務的跨可用區部署的高可用性。

優化後跨可用區流量降低了 95.4%。(見圖 13)

圖 13

五、後續的優化改進方向

目前的架構雖然解決了我們業務上的一些問題,但還是有一些不足之處可以改進。爲了可以就近訪問供應商,我們使用了一個獨立的 VPC 網絡來部署和測試我們的集羣,所以需要單獨在雲端部署相關的存儲依賴以及日誌監控組件,這樣無疑增加了運維的難度以及服務在不同雲上的遷移難度。

在最新的架構設計中針對這個問題我們計劃做如下改造,首先將需要在雲端計算並且依賴持久化存儲數據的功能遷移回攜程 IDC,這樣這部分數據就不用再傳到雲端。其次因爲公司在 AWS 的其他數據中心已經有一套成熟的環境,所以我們只需要配合 OPS 打通兩個 AWS 數據中心之間的 VPC 網絡,便可使用公司的日誌和監控框架,減少運維成本。

六、總結

本文通過攜程酒店直連在雲原生的實踐,分享瞭如何快速在雲上搭建一套穩定高效的生產環境實現快速交付、智能彈性,以及在雲上的一些成本優化經驗。藉助雲原生體系實現了基礎設施自動化,釋放一部分的運維工作,可以更多地投入到業務迭代,更敏捷地響應業務需求迭代,通過監控和日誌實現快速試錯和反饋。希望藉此能幫助到更多想上雲的團隊,少走彎路,擁抱雲原生帶來的好處。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/iVwq_klZoypf_6CVk11Z-g