京東服務市場微服務架構和積木式賦能挑戰
服務市場團隊在2018年完成了雲平臺京東服務市場的交接與POP平臺京麥外掛市場的系統融合,並承載著京東自營與三方越來越多服務進行商業變現的業務訴求。相對於傳統的電商系統,服務市場面對著的是更復雜的業務領域,更靈活多變的交易組合場景,如何讓系統具備積木式賦能的能力,通過鬆耦合架構設計具有系統高內聚性,把耦合度降到最低,進一步實現較為合理的微服務架構風格的應用系統,期間遇到了很大的挑戰也總結了很多經驗。本次分享和大家回顧這個艱辛卻有收穫的過程。
縱深化的業務整合
兩市融合 - 涅槃之路
2017年底,京東雲平臺京東服務市場交接到POP平臺京麥外掛市場進行系統融合,我們稱之為兩市融合。兩市融合是為了實現對外統一的服務入口,實現兩個系統變成一個系統,但當時這兩個市場卻是兩套完整的系統閉環。
融合專案是對兩個市場進行深度的融合改造,融合不僅是進行流程融合和資料融合,其中最難的就是同時支援雙邊業務的並行執行,所以,整個融合過程在服務釋出、服務稽核、服務展示、服務訂購和服務使用等環節對兩個系統原業務進行了大量的相容處理,造成了極高的系統複雜度和極差的穩定性。
融合方案並沒有採取單邊市場下線的方案,而是採取了將兩個市場裁取縫合的處理方式,交易流程使用了京麥外掛市場的流程,商品流程使用了服務市場的流程,這種融合方案現在看來的確不明智。
兩市融合 - 並行業務
並行業務的難度在於雙邊讀業務與寫業務的同時支援,因為不能簡單的下線一邊的業務,但當時對資料的讀寫入口不能完全梳理清晰,所以融合過程中對上下游各種業務需要相容支撐,因此在融合中的過渡階段產生了三套流程並行的尷尬階段,並且還需要同時雙寫三套資料庫表及同步多個數據快取,複雜度可見一斑。
當時兩個市場的兩個資料庫是獨立對外提供資料服務的,如何將兩個資料庫變成一個數據庫,是當時最大的難點。
而且服務市場作為一個交易系統,資料庫是系統的核心,不僅MySQL有很多從庫,還有Redis、ES、Solr、HBase等作為資料快取,所以在資料異構方面做了很多功夫。
兩市融合 - 流程融合 & 資料融合
流程融合包括服務釋出稽核流程融合、評價評分流程融合、服務搜尋流程融合、訂單訂購流程融合、結算流程融合、退款流程融合、取消訂單流程融合和發票流程融合等等。
以訂單訂購流程融合為例,由於服務市場和外掛市場融合切換是無縫的(不能停服務),且兩側訂購、訂單資料結構又不完全一致,同時資料切流又是逐步放量。所以訂購、訂單流程的融合採用資料庫雙寫的方式,所謂雙寫方式,是在寫原服務市場資料庫和外掛市場資料庫時,通過訂閱Binlog,使用BinLake框架訂閱寫入sql再整理資料寫入新資料庫。最終所有服務通過呼叫新庫進行查詢服務。
這種雙寫機制可以很好的進行回滾,當新流程出現問題的時候,可以切回到老資料庫進行降級。當新訂購流程出現問題時,也可以通過關閉切流控制影響範圍,採用老流程進行訂購訂單處理流程。
這裡補充說下,外掛市場和服務市場的老流程都是寫到各自的老資料庫中,而新流程其實也是寫到服務市場的老資料庫中,新資料庫的資料都是通過BinLake寫入的,這樣保證在流程融合過程中的資料一致性。
而流程融合完成後,即讀入口都切到新資料後,就可以逐步切換寫入口了,把兩套資料庫變成一套資料庫。切換的方式其實很簡單,主要是通過配置中心進行逐步切換寫流程,但要考慮切換失敗如何處理異常流,假如遺漏了一個場景,還有業務讀老資料庫,但這時老資料庫裡是沒有資料的,怎麼辦?
所以,準備了兩套方案,一套回滾,另一套補償。考慮到回滾的操作難度很大,因為程式碼回退、流程回滾可能出現的風險會很高,因為那時資料已經不一致了,所以首選方式是補償,當資料出現不一致時,啟動後端校驗Worker將資料補償到老資料庫中,並迅速修復線上問題。
兩市融合 - 系統架構
隨著融合的深入,服務市場的架構逐步演進成為經典的三層架構,底部是外部依賴,概括主要是京東商城和京東金融的中臺服務;中間是服務市場的服務層,包括服務引擎、商品中臺、訂購履約中臺和支付中心等系統;上部是服務市場的應用層,包括服務市場大前端、商家工作臺、服務商後臺等系統。
架構部署 - 呼叫關係
本著 SOA 微服務化的架構設計理念,將服務市場設計為模組化和層次化的架構風格,高層次模組呼叫低層次模組,低層次模組通過介面向上提供服務,以實現系統之間的解耦。但是對模組的設計粒度拆分的過細,這使得隨著業務的發展,整個系統變得愈加複雜,系統之間的業務呼叫關係也變得愈加混亂。
架構部署 - 隔離防腐
複雜的呼叫鏈路,必然造成業務之間的相互影響,所以,通過對服務市場從部署、資料庫訪問、服務PRC呼叫、訊息接收等進行了縱向垂直部署隔離,分為商智、京麥、服務市場等多套隔離部署層,實現即使任一垂直域無論因為伺服器還是資料庫問題,影響不會擴散到其他業務上。
化繁為簡 - 簡化架構
複雜的架構,不僅造成新需求消化越來越慢,而且系統也愈加的不穩定起來,這在未來的發展過程中,效率和成本都將成為很大的問題。所以,痛定思痛,決定進行簡化系統架構,將系統設計的越簡單越好,鏈路越短越好,流程越簡單越好。因為‘A調B’一定比‘A調B調C調D’的鏈路要簡單,而且出現問題更易於排查。
所以,我們進行了逆向微服務化的架構改造,即系統的整合,確立了三個中心和一個引擎的系統架構,且是多層次的服務對外提供服務,而不是由一箇中心層統一對外,要去中心化,微服務化的架構設計思想也是去中心化,即每個中心都可對外提供服務,因為層次降低和緯度降低之後,就非常容易定位問題。
系統複雜度等於系統個數加上系統之間的呼叫鏈路個數,相比簡化之後的架構,可見系統複雜度降低了多少。而且還在業務側逐步改造、遷移、下線一些老業務服務或功能,這相當於給系統做了瘦身,將無效程式碼都清理掉了。
化繁為簡 - 隔離防腐
經過改造後的服務市場,由於系統進行了整合,系統變少了,雖然系統的隔離防腐在部署上看似沒有什麼變化,但每個系統橫跨的業務層是變多了的,我個人認為這其實是就是元件化的方式,就是一個系統可以複用給多個業務場景。
服務化改造 - SOA
隨著兩市融合的終結,流程融合和資料融合的完畢,系統實現了統一的服務層,這使得對外提供服務的難度降低很多,否則一個服務在多個系統提供相似的功能,這出了問題是很難快速排查的,所以融合不徹底是無法實現服務化的,服務化也要求必須統一入口、統一流程化。
所謂系統架構的終極思想,就是降低軟體複雜度,不是把系統做的越來複雜,而是把系統複雜度做的越來越低。
當系統實現服務化之後,單品頁就不會三千多行的程式碼的業務邏輯,還呼叫了很多介面,而是通過服務化在Action層進行服務介面的整合。同時,也可以靈活的實現各個服務的降級處理,以提高系統的穩定性。
服務化改造 - 多級快取
MySQL作為當今主流的資料庫,業務中如果使用的好的話,決定能扛住上百萬,甚至上千萬的量,但是現在大多數系統做不到,這種情況下就要考慮如何做到MySQL防禦。服務市場是一個交易系統,如果把庫打掛了,那將造成系統不能生產,業務不能收錢,這是非常嚴重的線上事故。
早期的快取架構設計是Jvm-Redis作為熱點快取,但是在冷啟動情況下,可能會出現快取穿透,造成MySQL出現很大壓力。所以,後期設計完全避免這種穿透的可能,Redis完全作為資料儲存,與MySQL進行隔離,Redis查詢不到資料,就直接返回,與MySQL的資料一致性通過資料異構來實現。
服務化改造 - 資料異構
服務市場使用BinLake進行資料異構,即通過訂閱MySQL的Binlog日誌,通過接收JMQ進行資料異地構建儲存。
資料異構主要有兩種方式,一種是順序消費、另一種是並行消費。其中,在進行訂單、訂購的資料異構時是要求保證嚴格的順序性的,因為並行消費是無法保證訂單的先後順序的,所以可能造成資料不一致。
但順序訊息的問題主要是單點消費效率慢的問題,以及消費出了問題就會造成阻塞,之前使用伺服器進行消費,通過ip限制保證單點,後期切換到流式計算平臺(strom/flink)進行處理,流式計算在並行寫es和jimdb有天然的優勢,但如果異常情況下出現寫操作失敗,對於JMQ的重試系統要做好冪等操作的處理。
而商品資料異構是使用併發消費的,因為商品資料不需要保證嚴格的順序,但商品資料異構的問題,是一條商品資料在MySQL中是存在多張表中,而異構到ES或JimDB中就是一條記錄,那對於商品資料是訂閱那哪些表的Binlog呢?
所以,我們的實踐中商品資料異構是訂閱商品的主表,其他資訊通過反查資料庫獲取的。但這個場景下,併發訊息雖然會提高處理效率,但由於反查資料庫會造成額外的IO開銷,而且反查資料庫還是主庫,因為BinLake和資料庫主從同步都是基於Binlog,這兩者之間的速度是無法保證誰先誰後的。
最後,考慮系統誰也無法保證不出問題,所以還使用定時任務在每天一個時間點進行資料一致性的校驗。
積木式賦能挑戰
交易服務平臺
在過去的一年裡,不僅服務市場的系統架構發生了巨大的改變。在融合之後,思考的重心也逐漸變成了如何將越來越多的服務接入到服務市場上進行售賣,所以,工作上,一是對服務市場已售賣的服務進行搜尋優化、對先後端類目進行解耦、優化排行等,二是豐富服務市場業務場景覆蓋度,快速接入多樣服務入駐服務市場。
並通過拆解業務、抽象規則、能力下沉,構建積木式的交易服務平臺,實現快速接入官方&三方服務,賦能開普勒、無界零售、7Fresh、國際站等多個業務場景。
服務市場通過服務交易能力提升專案,實現了服務交易流程配置化,將早期入駐服務市場時間需要花費2~4周減少到0天。
流程配置化 - 交易管道
所謂交易管道,簡單說,就是當有一個訂單來了,通過一個流程從訂購、訂單、支付、臺賬、發票、退款等節點往下走,這就是一個管道。但是,如果每有一類服務,就做一個流程,如SAAS一套流程、質檢一套流程、ERP一套流程等,那最終只能通過堆人的方式進行開發,而這種開發效率也是極低的。
其實,通過對業務不斷的沉澱,你會發現大多數服務流程都是有很多相似性的,唯一不同的就是之間的配置,那我們把這個可以複用的功能提煉出來,稱為配置中心,用工作流的方式驅動這些資料在管道中進行流轉,這就是流程配置化。
流程配置化 - 配置中心
配置中心採用多級快取、資料庫拖底的方式來保障交易引數獲取效率和高可用,所以,在整個交易的全生命週期裡,都會依賴於配置中心,基於配置中心的引數進行流轉。
商品模版化 - 服務屬性
所謂商品模版化,就是對商品的屬性進行緯度化和屬性化。
參考京東商城的服務釋出流程,一個實體商品的釋出資訊,主要包括商品資訊、商品屬性、圖片、簡介,及最重要的銷售屬性。一個商品可以認為是一個SPU,而SKU是通過多個銷售屬性組合而成的,一個SKU才會確定唯一的價格和庫存。
商品模版化 - 模版引擎
基於模版引擎,在規則上進行剝離,在服務屬性低耦合下,可以通過模版的方式自定義一些服務的釋出資訊和規則,並實現屬性與履約規則的配置關聯,作用於交易和訂購履約中。
服務市場釋出的SAAS服務都是需要進行履約的,履約的方式主要有周期+版本、週期+模組、數量+模組等,其中版本與模組的區別在於訂購時升級與續費的邏輯不同。那釋出服務的銷售屬性如何與履約規則進行配置關聯,我們比較了三套方案,最終使用的是方案三。
總結
最後,希望將京東服務市場打造成為精品的交易服務平臺,做到服務市場更加穩定、交易流程更加便捷、接入服務更加高效。
同時,服務市場團隊也在不斷壯大,新思想的碰撞,有好的方面、也有壞的方面。我希望用自己的行動,不斷影響團隊,讓團隊變得更有凝聚力、更有戰鬥力。
作者介紹
作者:張鬆然
京東服務市場應用架構負責人,京東集團商家研發部架構師。10年的軟體開發和設計經驗,豐富的構建高效能高可用大規模分散式系統的研發、架構經驗。在京東的五年多時間,負責了京麥平臺的升級改造及歷次618和雙11備戰,最近負責了京東服務市場應用系統的整體架構設計工作,對鬆耦合平臺系統和微服務架構進行了深