使用微服務架構(gòu)重構(gòu)支付網(wǎng)關
是微服務重構(gòu)支付系統(tǒng)的系列文章。 之前的文章請參考:
在支付系統(tǒng)改進中,我們對原有系統(tǒng)做了整體的評估,選擇支付網(wǎng)關作為入手點來進行微服務架構(gòu)的改進。這里詳細介紹我們針對該模塊的改進過程,供參考。
原有系統(tǒng)情況
早期啟動的時候,對接的支付渠道不多,所有支付渠道和支付網(wǎng)關都實現(xiàn)在一個項目中,部署在一起。其中支付網(wǎng)關是整個項目的核心和入手點。它為各個業(yè)務方提供支付全流程的調(diào)用接口,簽約、代扣、支付、驗證,都是通過這個接口來實現(xiàn)的。整個系統(tǒng)使用SSH框架,架構(gòu)如下:
業(yè)務流程如下:
- 當接口被調(diào)用時, 首先執(zhí)行參數(shù)校驗,確認輸入的參數(shù)的合法性,驗證參數(shù)簽名是否正確。確認過程包括調(diào)用賬戶、用戶、支付方式、路由等服務來驗證用戶ID、賬戶、支付卡號、支付金額等參數(shù)。
- 根據(jù)輸入的支付方式,調(diào)用支付路由服務,獲取對應的支付渠道。
- 調(diào)用風控接口進行驗證,如果有交易風險,則阻斷本次交易。
- 生成交易記錄;
- 調(diào)用支付渠道提供的服務執(zhí)行支付。
- 根據(jù)支付結(jié)果,更新訂單狀態(tài);
- 通知商戶訂單執(zhí)行結(jié)果。
在實現(xiàn)上,原有系統(tǒng)實現(xiàn)的類結(jié)構(gòu)圖如下:
- 采用SSH架構(gòu),支付網(wǎng)關實現(xiàn)為一個大Apache Struts Action類,和支付相關的所有業(yè)務邏輯都實現(xiàn)在一個項目中。
- 支付網(wǎng)關承載大量的功能,實際上,它是將API網(wǎng)關和業(yè)務邏輯都混在在一起實現(xiàn)。 簽約、支付、代扣、驗證,都在這一個類中實現(xiàn),代碼行數(shù)超過1000行,邏輯十分復雜。
- 除了風控是進程外調(diào)動,其他的服務都是進程內(nèi)調(diào)用,通過springframework來管理各個service。
- 最終落地調(diào)用的支付渠道,是通過抽象的接口來對網(wǎng)關封裝渠道的差異。
在這個系統(tǒng)中對接了有30多個渠道,類規(guī)模達到2000個。隨著業(yè)務發(fā)展,問題越來越多。高峰期同時有5個渠道在并行開發(fā),還有大量的其他渠道對接問題需要修復。多個人同時修改一個項目代碼導致版本控制的工作驟增。上線頻發(fā)引起服務中斷也讓業(yè)務方很不滿。對支付網(wǎng)關的改進是一個循序漸進的過程。這里參考Arun Gupta的微服務六種設計模式,來描述我們所做的改進。
新網(wǎng)關設計 (Chain Pattern)
為了分解舊網(wǎng)關的功能, 我們設計了新的網(wǎng)關。在處理流程上,將其分為三個步驟,采用的是chain模式。
鏈式模式,如上圖所示,它調(diào)用服務A來獲取結(jié)果,而服務A是通過服務B來交互,B則會和C有交互。 整個過程類似同步的HTTP請求、響應處理。 這其中每個階段的調(diào)用,都是阻塞式的同步調(diào)用。每一步都會增加一些業(yè)務邏輯處理。
原支付網(wǎng)關難以維護的一個重要原因是其所承載的功能過多。我們首先根據(jù)用戶的使用場景,將支付網(wǎng)關承載的功能,按照支付產(chǎn)品來進行切分。 支付產(chǎn)品包括快捷支付、網(wǎng)銀支付、外卡支付等。 不同的產(chǎn)品,其對應的操作所使用的參數(shù)和流程也不一樣。以快捷產(chǎn)品為例, 新網(wǎng)關接收到請求后,根據(jù)用戶所選擇的支付類型,分發(fā)到快捷支付產(chǎn)品接口??旖葜Ц懂a(chǎn)品接口調(diào)用工行借記卡通道來執(zhí)行支付,通道最終落地到工行接口的調(diào)用來實現(xiàn)支付。 支付操作完成后,工行接口通知到通道,通道通知到產(chǎn)品,最終逆向傳遞到網(wǎng)關接口,并最終發(fā)送給調(diào)用方。 在這里面,支付網(wǎng)關負責分發(fā)、驗簽等基本功能,支付產(chǎn)品負責參數(shù)校驗、路由、生成交易記錄等功能。最終的支付操作是落地到支付渠道去執(zhí)行。
網(wǎng)關拆分(Proxy Pattern)
如上所述,支付網(wǎng)關按照使用場景進行拆分。我們采用完善一個、接入一個的原則,在保留舊網(wǎng)關的功能的同時,開發(fā)完善新的網(wǎng)關和支付產(chǎn)品。等所有流量都打到新網(wǎng)關上去之后,舊網(wǎng)關就直接廢棄了。為了達到這個目標,我們引入了代理模式:
代理模式和聚合模式類似,不同點在于,它會根據(jù)業(yè)務邏輯需要僅選擇一個微服務來調(diào)用。微服務中,我們經(jīng)常會用代理模式來構(gòu)建API網(wǎng)關。
我們首先按照所支持的支付方式,對支付網(wǎng)關做分解,拆分為為網(wǎng)銀、快捷、話費、賬戶、外卡、虛幣等支付產(chǎn)品。新網(wǎng)關接口模塊是一個proxy,本身并未實現(xiàn)任何業(yè)務邏輯,它的工作是將用戶請求發(fā)送給合適的支付產(chǎn)品去處理。如果這個產(chǎn)品還沒有實現(xiàn),則將其轉(zhuǎn)發(fā)到老網(wǎng)關去執(zhí)行。這樣帶來的好處是,我們不需要對老網(wǎng)關做任何改動。而且,如果某個支付產(chǎn)品在重構(gòu)過程中出現(xiàn)問題,我們可以很快切回到老網(wǎng)關去。
支付產(chǎn)品 (Aggregator Pattern)
支付產(chǎn)品是對原有支付網(wǎng)關的業(yè)務流程實現(xiàn)的一個重構(gòu),按照各個支付產(chǎn)品所支持的功能以及流程來簡化原混合在一起的設計。比如快捷支付需要簽約和支付,而網(wǎng)銀支付則不需要簽約。 在支付產(chǎn)品本身的實現(xiàn)上,我們使用的是聚合模式。
聚合是最常見的微服務設計模式,它是一個高層次的微服務組合,供其他服務調(diào)用。 在這種情況下,聚合器會從其他的微服務中收集數(shù)據(jù),做業(yè)務邏輯處理,然后發(fā)布成一個服務終端。其他有需要的服務可以調(diào)用它。 聚合器設計的要點是要遵循DRY(Don’t Repeat Yourself)原則。如果有多個服務需要訪問A,B,C服務,那建議的處理方式是,針對這些使用,提煉一個處理邏輯出來,將A、B、C封裝為一個新的服務,這個服務可以獨立的演化。
支付產(chǎn)品中調(diào)用的各個服務,包括支付方式管理, 支付服務管理,支付路由管理、支付記錄管理等,都被重構(gòu)為微服務,在支付產(chǎn)品的實現(xiàn)中,通過Aggregator 模式進行調(diào)用。
在支付產(chǎn)品的實現(xiàn)流程中,首先需要對參數(shù)進行校驗,校驗成功后,調(diào)用風控檢查該交易是否可以放行。這兩個操作,在處理上可以并行,使用的是分支模式。
分支模式是聚合模式的擴展,可以允許同時調(diào)用兩個或者更多的微服務。
如上,采用分支模式, 使得數(shù)據(jù)校驗和風控可以并發(fā)執(zhí)行。由于風控相對耗時較長,而訂單中需要校驗的數(shù)據(jù)較多,這兩個操作有必要并發(fā)執(zhí)行。
支付通道 (Aggregator Pattern)
支付路由根據(jù)用戶選擇的支付方式對支付通道進行篩選,選取合適的支付通道。支付產(chǎn)品調(diào)用該通道的接口來最終落地完成支付服務。 每個支付通道對接也被實現(xiàn)為微服務,在支付產(chǎn)品中調(diào)用。
通知商戶 (Asynchronous Messaging Pattern)
支付產(chǎn)品執(zhí)行的***一個步驟是通知調(diào)用方支付的結(jié)果。 原系統(tǒng)實現(xiàn)是將這個步驟耦合在原有代碼中,容易受到調(diào)用方接口的穩(wěn)定性的影響。 為此,這里采用異步消息的模式來進行重構(gòu):
異步消息一般用于對流程中可以異步執(zhí)行的操作做分解,將它從原流程中分離出來,通過消息機制來異步執(zhí)行。 支付產(chǎn)品在完成支付服務后,發(fā)出消息到訂單消息隊列中。 商戶回調(diào)處理程序接收到消息后,調(diào)用商戶回調(diào)接口告知支付結(jié)果。 此外,風控、BI系統(tǒng)等,也可以使用這個消息來同步訂單數(shù)據(jù)。
總結(jié)
這里簡單介紹了支付網(wǎng)關重構(gòu)的過程,以及如何使用微服務設計模式。 當然,這里我們也忽略了很多細節(jié),比如支付網(wǎng)關所依賴的基礎服務的開發(fā)。 最終的支付網(wǎng)關的架構(gòu),參考《支付網(wǎng)關設計》一文。這里涉及到的支付路由、支付記錄、支付風控等模塊的設計,后續(xù)也會在本博客中做介紹。 微服務化改造并不難,需要的是對原有系統(tǒng)有深入的了解,然后運用各種模式來拆分,庖丁解牛。拆分的每一步都需要注意,在設計上,需要考慮一旦出現(xiàn)問題即可回滾。
【本文為51CTO專欄作者“鳳凰牌老熊”的原創(chuàng)稿件,轉(zhuǎn)載請通過微信公眾號“鳳凰牌老熊”聯(lián)系作者本人】












































