攜程商旅訂單系統架構設計和優化實踐

作者簡介

 

Gavin, 攜程技術專家, 致力於系統優化、重構和開發效率提升。

概述

攜程商旅是一站式互聯網差旅服務平臺,爲客戶提供差旅管控、預訂、出行、結算、成本、風控等服務的在線 TMC(Travel Management Companies)。主要產線有:機票、酒店、火車票、打車、接送機、包車、租車、汽車票等。攜程商旅訂單系統針對 B 端客戶定製化需求多樣性,商旅產線豐富性,TMC 業務與產品業務結合的複雜性等,對訂單系統架構進行了優化。

一、背景介紹

訂單系統作爲入口,承上啓下,涵蓋了訂單生命週期中所有的流程管理、TMC 管控、創單中心、費用中心、履約中心、服務中心、聚合中心以及投訴理賠管理等。訂單打通用戶、商家、產品、庫存、訂後等關鍵業務,是驅動交易全流程運轉的核心。

訂單系統具備的能力,可以按照下面兩個維度和多個角度進行切入拆解:

員工視角:預定、公賬墊付、個人支付、行程管理、退改服務、物流跟蹤等;

財務視角:成本中心、交易流水、費用明細、賬單報表、報銷憑證等;

審計視角:審批授權、差旅管控、數據合規、政策合規、風控、反作弊等。

客戶實施視角:賬戶配置快照、訂單聚合服務、API 對接等;

供應商視角:商家拆單、訂單狀態管理、費用結算、售後管理等。

攜程商旅訂單系統在早期爲了快速滿足業務需求,產線爲純縱向獨立模式,在業務的快速上線、風險隔離,有效地降低產品之間的耦合性作用明顯。隨着業務的快速發展、產品豐富度增加、產品之間業務關聯程度深化、客戶的定製化需求增多和創新型產品快速上線,當前系統架構出現了單一臃腫、耦合嚴重、功能重複、流程不統一、監控和運維弱等各種問題。

二、基於業務特性的設計原則

2.1 分層設計 - B 端系統 C 端化

從預定視角能夠感知到的系統功能:快速下單、支付、出票、確認供應商等。這一點無論 C 端還是 B 端都是相通的,使用對象都是 “人”,核心目標就是確保用戶的行程可以順利起飛、出行、入住等。C 端系統的功能是 B 端系統的基礎,從時間維度劃分以下流程,在此基礎上 B 端系統會有其特有的業務屬性被嵌入。

這裏需要避免按照傳統的思維梳理流程圖,將 B 端的功能與 C 端的功能作爲一個整體的流程開發。B 端特有的邏輯和服務應該獨立開發並且與產品、產線解耦,通過服務編排、流程引擎等實現功能可配置、可擴展、可插拔的方式對訂單系統進行統一的調度和驅動,實現 B 端業務特性與 C 端邏輯分離和解耦,達到產品需求 C 端化。

B 端嵌入功能:選擇審批人、成本中心;差旅申請、管控校驗;支付賬號(公賬)、費用政策、報銷憑證規則等。

B 端嵌入功能:發起審批(審批人通過、拒絕、終止);公賬扣款、公司信用支付、費用流水;公司對接推送等;

B 端嵌入功能:退改審批流程、管控校驗、打卡校驗;訂單金額、訂單狀態、票號狀態終態的合規驗證;未出行訂單自動處理流程;費用流水處理、報銷憑證處理等;

2.2 流程設計 - 產線多、共性小

從多產線中抽取出共性(去重複、標準化),針對 B 端系統所具有的定製化、碎片化、特定性等需求,提供通用、統一的標準化流程方案。在標準化流程的基礎上再結合訂單系統特有的訂單狀態、訂單事件、票號狀態等,抽象出流程引擎,實現可配置、可擴展的標準化流程,從而達到化繁爲簡的效果。

2.3 快照設計 - 管控粒度細、維度多

差旅管控信息(賬戶配置、支付賬號、審批授權、差旅標準、政策執行人等)作爲差旅業務的基礎信息,對其任何的改動都至關重要,一方面把每次的更改記錄都保存下來。另一方面在每次交易訂單的各個場景,需要將當時差旅管控信息持久化。以此作爲各個子系統交易和運行的基礎服務實現統一收口,同時以便問題的排查、處理投訴、維權、溯源等。

三、架構演進

系統架構圖

3.1 Order Consolidation - 數據抽象

縱向模式向分層模式演進最大的挑戰是不同產線之間的數據庫的橫向,任何數據層面的改動和遷移猶如行駛中的汽車更換輪胎。系統在初期通過縱向的訂單詳情接口滿足前端、各子系統、IM 等不同場景,此模式簡單清晰,數據全量輸出,但是帶來的問題也是顯而易見的:DB 壓力過大、接入複雜、學習成本高、數據耦合等。

通過借鑑數據倉庫建模的方式,以 offline 系統思維來降低 online 系統的複雜性。以子系統的數據詳情服務作爲事實表 Fact, 根據不同的業務場景和粒度輸出維度表 Dimensions。較少的系統是從頭開始、從輪子開始建造,都是在已有基礎上優化和迭代,通過通用數據冗餘和增加維度數據聚合輸出服務, 實現數據層面的橫向。

1)數據建模、數據冗餘,降低系統複雜性

訂單數據進行統一的抽象建模。以訂單基礎數據、常用數據、各子系統數據行程服務, 報銷憑證,退改服務,管控服務等詳情數據作爲事實表 Fact,  建立各種維度表 Dimension:訂單基礎數據、產品基礎數據、賬戶配置快照、行程信息、支付費用信息、TMC 管控詳情等。

2)核心資源隔離和保護、確保關鍵流程高可靠性,支持單量的快速增長

隨着運維能力和分佈式系統的發展成熟,業務系統的 API 和微服務較容易水平擴展。性能瓶頸不容易解決主要是在 DB 層面,並不能輕易的擴展分庫分表或者引入新的存儲服務。訂單庫和 online DB 是整個訂單系統交易的基礎,降低數據庫 IO 壓力、保護關鍵路徑和確保訂單系統全流程的驅動順暢需要儘可能的減少 DB 執行負荷重的任務:通用數據查詢、列表查詢、複雜查詢、聚合查詢、模糊查詢、高頻查詢等,而這些場景基本上做到 NRT(near real-time)準實時輸出即可。OCS 通過冗餘落地的準實時數據和提供一系列的 API 服務達到隔離核心資源的目的。

3)大幅降低客戶端學習成本、接入成本,支持業務的快速迭代

一個訂單從預定到最終的結算經過較多的子系統和數據處理,整個訂單生命週期產生的數據大而全、零碎、分散在各個 DB 和各個子系統,對於 client 端接入需要感知較多的邏輯和熟悉衆多的交互 API,不僅學習成本高,同樣一個場景在不同的產線需要多次實現。

對於較多的場景如列表查詢、基本數據查詢、交叉推薦查詢等通過數據的統一抽象、融合、落地實現流程統一、API 統一、交互統一大幅簡化接入端的成本,包括產品、BI、業務的取數規則等。

Order Consolidation Service

3.2 Order Message - 客戶端減負

設計 API 和服務時通常考慮較多的是 API 如何設計、交互、傳參、client 需要遵循的各種規則,較少的考慮 client 可以不做什麼,client 在享受服務的同時應該可以不做一切可以不做的事情。傳統上消息發送服務設計爲提供不同消息的發送接口,由各客戶端根據各自的業務流程處理指定模板、類型、動態內容等調用對應的接口, 這個看起來是符合高內聚、低耦合的通用設計原則的。

原流程發送一個消息需要 client 端調用多個數據源查詢數據、各種邏輯判斷、消息類型、發送場景、模板處理等。新的設計將各個消息抽象爲產線,場景模式對應一套配置和一套數據源 API(統一爲 key-value 輸出),註冊在消息中心,類似網卡插入主板後,需要安裝驅動程序實現可插拔的方式大幅減少 client 端的工作,client 只需要傳一個場景即可實現一系列消息的發送。根據實際的業務場景,需要根據下面 6 種場景的排列組合,觸發一個或多個消息的發送。

1)發送場景:創單、支付、確認客戶、出行、成交等。

2)發送模板:支付類型、訂單處理階段、訂單狀態等。

3)發送語言:中文簡體、中文繁體、英文、日文、韓文等。

4)發送類型:短信、郵件、微信、企業消息、站內信、手工操作等

5)收 件 人: 聯繫人、預訂人、出行人、授權人。

6)數據來源:訂單數據、成本中心子系統、審批子系統、賬戶配置子系統,消息附件等

通用消息中心 - 配置服務

3.3 Order Conductor - 服務編排

1)服務拆分和邊界確定之後,系統之間的交互同樣需要統一的規則和整體上的設計。尤其需要避免單一事件觸發後,需要調用一系列的 API 和較爲複雜的交互流程,導致調用鏈過長,服務之間相互調用、耦合嚴重等問題。

2)服務編排是根據業務邏輯,以串行、並行和分支等結構編排多個 API 及函數服務爲工作流,達到統一調度和指揮各個業務子系統,同時更加有利於事件驅動機制的落地。極大簡化了多個服務之間組合調用的開發和運維成本,更加專注於業務本身。要實現服務編排、自由組合、靈活擴展滿足下面的條件是基本前提。

任務原子化:每個接口或 API 拆分合理、職責單一,實現任務的原子性。

數據私有化:每個任務都有一套對應的數據表,並且僅自己本身可以操作和訪問。如果沒有實現數據庫和資源的隔離,那任務原子化也就不存在,需要避免多個任務讀寫同一數據表和資源。

契約相通:任務編排,契約相通才能實現服務的統一調度。契約的設計必須是高度精簡、覆蓋全場景的。訂單系統全流程驅動中一定會有的是:訂單號、場景。如事件:退票完成,各被調用的服務通過數據反查獲取數據,實現服務之間通信的契約大幅簡化, 而不是依賴調用端的各類傳參。

事件驅動:定義全流程統一的事件列表枚舉,非查詢類的操作完成後觸發其對應的事件通知編排服務中心,根據流程配置統一調度實現服務編排。尤其需要避免的是各個服務之間相互直接調用,相互訂閱廣播通知導致系統的耦合和邊界不清晰,以及服務擴展較差。

服務冪等性:服務的統一調度,不可避免的會出現多次被調用和觸發的可能,每個原子性任務都需要根據自己的業務支持冪等性。

重試機制:與服務冪等性相輔相成、缺一不可,編排服務中心需要統一調度,就需要在配置和設計上支持任務的可重試、可降級和最終到達。

DB 訪問降頻:由於任務的原子性拆分,每個任務執行依賴的數據都需要調用詳情查詢服務獲取需要的數據,即使是相同的數據也是需要各自獲取導致數據庫 IO 壓力的大增。針對這個場景有很多種方案。

Order Conductor

3.4 Order Fulfillment - B 端場景

B 端用戶需求與傳統的企業級軟件有非常多的相似點,定製化和多樣性是最爲顯著的共同點。商旅 B 端客戶即使是基本的功能:支付流程、發單方式、管控流程、通知內容等都有顯著的差異。以訂單系統酒店產線舉例,下面的訂單屬性和訂單狀態各個值排列組合出 50 種以上需要處理的流程,這僅是酒店一條產線。

訂單屬性:訂單類型、授權順序、支付方式、墊資方式、配置流程、國際國內、三方協議等,

訂單狀態:已提交、未提交、授權通過、授權拒絕、已支付、已出票、已取消、確認客戶等;

不僅微服務之間需要統一調度和流程配置,而對於每個應用或每個服務同樣如此。訂單系統僅通過工作流驅動並不能滿足要求,其最爲重要的屬性就是訂單狀態、訂單事件等觸發和驅動訂單系統的流轉。通過開發基於訂單狀態、訂單事件結合工作流開發流程引擎達到可配置、可擴展、易維護的目的,而又避免引入較笨重的開源工作流引擎達到 “夠用即可”:

流程引擎

狀態驅動 + 流程引擎

四、論述與總結

什麼是好的設計?

什麼應該橫向?什麼應該縱向?

什麼應該縱向? 業務上共性少,差異大,對於客戶需求需要快速響應,業務上需要快速試點和產品創新,正如圖第一象限業務層展示的特點:特殊性,可變性。所以業務層在系統上應該縱向,隔離,但是在流程上標準化,可配置化,確保其靈活快速響應,儘可能少的涉及具體實現。

什麼應該橫向? 高確定性、高通用性功能應該橫過來供不同的團隊和子系統共享,作爲各個產線子系統的基礎,同時也是支持業務在已有系統上快速上線,創新,試點的平臺。

當業務需要快速的上線和需要速度運行,快速推向市場的時候,我們應該讓業務、產線分開快跑,應該把業務變成縱向的,獨立成建制的往前快速推進,摧枯拉朽,策馬狂奔。隨着單量的增長和業務的延伸,尤其各產線趨同功能變多,定製化需求和創新性需求增多,合規性性要求越來越嚴格,系統就暴露出大量問題:大量低水平重複建設,重複開發,效率低下,運維困難,任何新功能,新產品上線都需要從輪子開始建造。當我們需要效率、要積累、要沉澱的時候,尤其需要在已有系統上快速創新、試點新的產品時候,就非常明顯要把有些東西橫過來,從整體上規劃和設計,讓整個系統架構統一,流程統一成支撐體系包括技術沉澱,子系統中臺化演進讓其能夠有辦法共享給其他子系統和團隊。

什麼叫中臺,爲什麼需要它?中臺被過度神化過,也被極端的污名化。中臺並無對錯,主要取決於設計與邊界。其被詬病主要原因:

1)圈地運動:什麼都能做,什麼都可以做,基於不能重複建設的原則各 client 被強制要求接入。基於原則而實際上是無原則的開發模式,導致系統臃腫、邊界不清晰、耦合嚴重,不能通用而被通用只能通過給 client 制定各種條條框框和特殊定義來約束系統之間的交互、接入成本和溝通成本高,反映不夠靈活,對於創新型的業務不能快速的支持,需要反覆的溝通和規則制定,不僅沒有享受到便利,反而成爲了負擔。是一種明顯的山頭主義,勢力範圍的劃分。

2)代理式中臺: 高舉高內聚、低耦合的偉大旗幟,這也不能做,那也不能做,將 client 視爲負擔而非流量。client 需學習各種接入規則和傳參契約,接入成本高和使用複雜,不同渠道稍有邏輯不一致需要 client 自行處理,某種意義上說僅起到轉發的作用。中臺實際上是一個橫向策略。如果你要速度,要快速,要機動靈活,一定是這根杆子從上到下,都是一個人或一個團隊負責,這是最快的。而如果 client 需要感知各種流程,等於是邏輯分散,沒有做到真正的抽象和下沉。業務中臺需從整體上設計基於配置化編程滿足不同渠道的需求,而又不打破低耦合的原則,而非僅僅是個代理,是個類似基礎架構的網關。

3)資源壟斷:壟斷了資源輸出和對外交互,client 除了接入無其他選擇。同時又受制於團隊體量,團隊話語權,ROI 等各種因素得不到排期或列爲低優先級任務。

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