聚合支付架構(gòu)從零到一
0 前言
聚合支付主要是就是一個將所有的第三方支付米酬,通過借助形式融合在一起胳赌,相當于對接一個支付接口,就可以使用各種支付的場景夏醉。如便利店購物爽锥,貼個碼,上有微信支付畔柔,支付寶等各種支付氯夷。
它主要是針對一個微小商戶進行一個收款工具,讓商家他那邊會有一個收錢吧商戶通靶擦,第一個可以實時的收聽語音報告腮考,當前用戶付款多少錢雇毫,第二個就是他可以去實時查看賬單,了解當天營業(yè)額踩蔚。
還有一個產(chǎn)品就是pos機棚放,主要是一款生態(tài) pos,它里面不僅繼承了我們一個我們這個具備支付系統(tǒng)提供的服務(wù)馅闽,就比如微信支付寶飘蚯,它們還集成了一個刷卡的功能,就是磁條卡芯片卡福也,還有各種支付方式局骤。本文聚合支付只涉及交易流,不涉及資金流暴凑。
1 V1.0系統(tǒng)
-
工期短
基本上所有新項目都這尿性峦甩,天天被領(lǐng)導(dǎo)鞭策趕進度
-
業(yè)務(wù)不熟
不知道聚合支付到底做啥的,支付流程啥樣现喳?畢竟每個公司支付業(yè)務(wù)其實完全不一樣凯傲,無法照搬!
-
交易量小
當時的交易量是只有前端的一兩個產(chǎn)品在使用嗦篱,每天的交易筆數(shù)也很小
-
人員缺乏
新成立的團隊做新項目研發(fā)冰单,那就只有我和另一十年老鳥同事
該背景下完成 V1.0系統(tǒng)架構(gòu),即虛線圈默色,具體分工:
- 交易前置
- 交易網(wǎng)關(guān)
直接操作 DB 沒做甚至緩存的優(yōu)化球凰。
- 交易前置:支付核心業(yè)務(wù)處理,如記錄商戶交易流水腿宰、對接各個支撐服務(wù)
- 風(fēng)控系統(tǒng):交易單日/單筆限額呕诉、商戶黑名單、欺詐行為識別等風(fēng)險因素控制
- 路由系統(tǒng):通過設(shè)定的優(yōu)先級吃度、限額等路由規(guī)則甩挫,選擇合適的渠道,保證成功率椿每,降低成本
- 交易網(wǎng)關(guān):負責(zé)所有支付渠道的報文包裝伊者、數(shù)據(jù)加密、協(xié)議轉(zhuǎn)換间护、簽名驗證亦渗、狀態(tài)映射
當時就做這樣簡單架構(gòu),第一個開發(fā)比較快汁尺,直接拿需求進行改代碼法精,方便測試以及上線。經(jīng)幾個月交易猛增,發(fā)現(xiàn)
2 系統(tǒng)瓶頸
2.1 渠道隔離
當時對接了幾個渠道搂蜓,特別渠道不穩(wěn)定的話狼荞,如資源不可用、網(wǎng)絡(luò)問題帮碰,導(dǎo)致超時相味,就會把所有渠道交易全部影響,級聯(lián)反應(yīng)導(dǎo)致交易鏈路雪崩殉挽。系統(tǒng)哪邊掛了之后立馬要趕緊聯(lián)系丰涉。所以說這個渠道隔離放在第一位首要的。
2.2 接口膨脹
特別涉及相似業(yè)務(wù)的此再,如消費昔搂、撤銷、退款接口输拇,就每個業(yè)務(wù)類型都有這幾個接口,隨業(yè)務(wù)發(fā)展贤斜,也難維護策吠,開發(fā)每次來個需求都考慮到底是改哪個接口,要不要都改瘩绒。
2.3 動態(tài)擴容
聚合支付很多交易異步猴抹,用戶下單時,我們會立即返回就下單成功锁荔,或者下單失敗蟀给,但是這個交易有沒有消費成功,我們需要設(shè)置定時的任務(wù)去查詢最終付款結(jié)果阳堕。
2.4 定時調(diào)度
它需定時跋理、定點、定量拉取訂單處理恬总,如拉取數(shù)據(jù)太多OOM前普,太少很多交易得不到執(zhí)行。分布式下如何充分提升并發(fā)前提下充分使用機器資源變緊迫壹堰。
2.5 配置分散
傳統(tǒng)將配置文件存放在每個節(jié)點拭卿,每次升級都要運維手動改。風(fēng)險高且不好維護贱纠。
3 V2.0系統(tǒng)
3.1 設(shè)計方向
- 穩(wěn)定:支付系統(tǒng)的根基
- 支付體驗:用戶使用支付功能時感知零延遲
- 低耦合:模塊間減少依賴峻厚,需求變動風(fēng)險控制在最小范圍
過程試了多種方案,最終演變?nèi)缦孪到y(tǒng)架構(gòu):
服務(wù)劃分三條線谆焊,綠色和中間紅色和最下面一條橙色:
綠色:交易核心惠桃、交易網(wǎng)關(guān)
任務(wù)作業(yè)和查詢網(wǎng)關(guān),獨立部署
這倆業(yè)務(wù)線通過MQ解耦。
- 再獨立查詢服務(wù)刽射,對前端業(yè)務(wù)僅提供流水查詢功能
3.2 業(yè)務(wù)流程
業(yè)務(wù)發(fā)起一筆消費军拟,先進入支付核心初始化流水、風(fēng)控風(fēng)險識別誓禁、渠道路由懈息、渠道網(wǎng)關(guān)報文組裝、上送摹恰、渠道應(yīng)答辫继。異步交易發(fā)送消息至 MQ 集群,任務(wù)作業(yè)監(jiān)聽消息俗慈,put 緩存姑宽,定時任務(wù)拉取進行狀態(tài)查詢,業(yè)務(wù)方通過查詢服務(wù)查看該筆交易支付狀態(tài)闺阱。
3.3 前置優(yōu)化水平方向
<img src="https://my-img.javaedge.com.cn/javaedge-blog/2024/06/e71bbccbed3f07350c4e9af3dc0f44f9.png" style="zoom: 33%;" />
- 接入層:將共性接口統(tǒng)一炮车。如下單,所有業(yè)務(wù)酣溃,不管微信支付還是啥瘦穆,都歸為下單,具體業(yè)務(wù)通過 serviceId 標識
- 服務(wù)層:共性邏輯赊豌,也就是核心邏輯全部抽離出來扛或,然后進行統(tǒng)一下沉,作為底層服務(wù)碘饼,上層業(yè)務(wù)全部通過 serviceId 配置化實現(xiàn)熙兔,這樣的話盡量去少改動核心業(yè)務(wù)邏輯
- 緩存層:隨交易量增長,初代系統(tǒng)很多業(yè)務(wù)查詢直連DB艾恼,有很大性能影響住涉。所以就在 DB 之上將所有消費交易信息緩存,后續(xù)所有查詢蒂萎、更新操作全部打到緩存層秆吵,主要為提升服務(wù)性能
<img src="https://my-img.javaedge.com.cn/javaedge-blog/2024/06/5f72d08aad1d6c5ee454e909d6055b61.png" style="zoom:50%;" />
3.4 前置優(yōu)化垂直拆分
- 核心交易:交易核心鏈路,用戶感知最明顯五慈。如支付失敗纳寂,用戶立馬感知,投訴或電話客服泻拦,該模塊也包含退款業(yè)務(wù)
- 任務(wù)作業(yè):將處理中的交易進行狀態(tài)同步毙芜,和核心交易通過MQ解耦
- 查詢服務(wù):僅對公司內(nèi)部提供一個交易狀態(tài)查詢功能
3.5 任務(wù)作業(yè)
內(nèi)部查詢策略設(shè)計為兩個隊列、一個批處理:
-
內(nèi)存隊列:實現(xiàn)如延遲10s争拐、間隔5s或很多銀行使用 2 的 N 次方進行查詢
該隊列主要針對單筆交易執(zhí)行快速狀態(tài)同步腋粥,提升用戶體驗
"2的N次方進行查詢"這個策略一般是在系統(tǒng)設(shè)計中對于狀態(tài)查詢的優(yōu)化策略晦雨。如一個操作需要查詢外部系統(tǒng)以確認狀態(tài),第一次查詢在操作完成后立刻執(zhí)行隘冲,若沒有得到確認闹瞧,那就等待一些時間后再查詢一次。這里的"等待一些時間"就可能采取"2的N次方"的間隔策略展辞。
如第一次查詢失敗后奥邮,系統(tǒng)會等待21(也就是2)秒再查詢一次,如果還是失敗罗珍,那就等待22(也就是4)秒后再次查詢洽腺,以此類推。這樣做的好處在于可以避免在接口繁忙的時候造成過度查詢覆旱,對接口進行壓力保護蘸朋,同時也節(jié)省了系統(tǒng)資源。 緩存隊列:基于Redis集群扣唱,結(jié)合分布式調(diào)度框架 Elastic-Job 設(shè)計藕坯。主要針對狀態(tài)延遲的訂單,進行批量狀態(tài)同步
DB批處理:結(jié)合 Elastic-Job 設(shè)計画舌,主要提供人工干預(yù)的入口堕担,當渠道延遲比較長、或者渠道異常的情況下曲聂,執(zhí)行批量狀態(tài)同步
3.6 分片策略
任務(wù)分片:把一個任務(wù)分散到不同機器運行,既解決單機計算能力上限問題佑惠,也降低部分任務(wù)失敗對整體系統(tǒng)影響朋腋。
elastic-job 不直接提供數(shù)據(jù)處理的功能,只將分片項分配各個運行中的作業(yè)服務(wù)器(即Job 實例膜楷,部署在一臺機器上的多個 Job 實例也能分片)旭咽。開發(fā)需自行處理分片項與真實數(shù)據(jù)對應(yīng)關(guān)系。
數(shù)據(jù)分片:訂單號取模存儲(zset)
3.7 數(shù)據(jù)結(jié)構(gòu)
- 有序集合(zset):按分片邏輯赌厅,將訂單號取模穷绵,存放至對應(yīng)隊列
- string:交易明細序列化存儲
設(shè)計思路
- MQ 消費者(作業(yè)節(jié)點),接收到消息后特愿,將數(shù)據(jù)存入緩存
- 作業(yè)節(jié)點根據(jù)分片項仲墨、score 范圍,定時從對應(yīng)的緩存隊列中獲取指定數(shù)量的訂單號
- 業(yè)務(wù)循環(huán)處理揍障,根據(jù)訂單號再去緩存中獲取對應(yīng)的詳細信息
- 執(zhí)行查詢邏輯
zset元素數(shù)據(jù)過期目养,需業(yè)務(wù)自己處理,可單獨建立檢測機制毒嫡,也可每次執(zhí)行業(yè)務(wù)時執(zhí)行判斷癌蚁,過期則移除,不然集合越來越大。
4 高可用設(shè)計
4.1 渠道隔離
高并發(fā)訪問下努释,系統(tǒng)所依賴渠道穩(wěn)定性對系統(tǒng)影響很大碘梢,外部依賴存在大量不可控因素,如網(wǎng)絡(luò)連接變慢伐蒂,資源突然繁忙煞躬,暫時不可用,選型容錯開源框架 Hystrix饿自,隔離方案選擇 thread汰翠。
4.2 查詢網(wǎng)關(guān)
交易系統(tǒng)中,查詢業(yè)務(wù)量一般是支付業(yè)務(wù)的 6 倍昭雌,甚至更高复唤,這樣對查詢服務(wù)性能就會有更高的要求。減少對核心交易影響烛卧,提升穩(wěn)定性佛纫。
4.3 通道商戶緩存
通道信息(機構(gòu)號、商戶號总放、密鑰等)屬靜態(tài)信息呈宇,初次使用時存入分布式緩存系統(tǒng)(設(shè)置TTL,防止僵尸數(shù)據(jù))局雄,同時增加手動修改的入口甥啄,方便人工干預(yù)。
- 千里之堤毀于蟻穴:用容錯就是避免蟻穴變大炬搭,依賴服務(wù)不可用時蜈漓,服務(wù)調(diào)用方通過技術(shù)手段,向上提供有損服務(wù)宫盔,保證業(yè)務(wù)柔性可用
- 線程池資源隔離:Java 的 Servlet 容器 Tomcat或 Jetty 都是多線程模型融虽,用 Worker 線程處理請求。當業(yè)務(wù)請求打滿 Worker 線程的最大值后灼芭,剩余請求被放到等待隊列(或拒絕)有额,若等待隊列也滿,那這臺 Web Server 就會拒絕服
QPS 較高的服務(wù)彼绷,那基本上這種場景下巍佑,你的服務(wù)也會跟著被拖垮。假如上游服務(wù)也沒有設(shè)置合理的超時時間苛预,故障就會擴散句狼。這種故障逐級放大的過程,就是服務(wù)雪崩效應(yīng)热某。采用容錯框架 Hystrix 解決此問題腻菇。 通過 Hystrix 命令模式胳螟,將每個類型的業(yè)務(wù)請求封裝成對應(yīng)的命令請求。每個命令請求對應(yīng)一個線程池筹吐,創(chuàng)建好的線程池是被放入到 ConcurrentHashMap 中糖耸。
盡管線程池提供線程隔離,也要有超時設(shè)置丘薛,不能無限阻塞以致于線程池一直飽和嘉竟。
Hystrix 線程監(jiān)控
實時展示各業(yè)務(wù)線程池資源,研發(fā)以此為參考評估資源是否夠用洋侨、是否需升級機器資源等:
2.0全面對接內(nèi)部監(jiān)控平臺舍扰,關(guān)注:
- 節(jié)點耗時監(jiān)控:如哪個時間點、哪個節(jié)點耗時較多希坚,通過百分比直觀看出瓶頸
- 成功率監(jiān)控:折線圖定時刷新數(shù)據(jù)边苹,將各個時間點的交易記錄數(shù)、成功筆數(shù)裁僧、失敗筆數(shù)進行匯總計算个束,渠道接口異常時可以第一時間發(fā)出告警
- 應(yīng)答碼監(jiān)控:應(yīng)答碼 TOP 排行榜,方便研發(fā)分析數(shù)據(jù)聊疲,提前將問題通知給渠道茬底,減少后續(xù)可能出現(xiàn)更大的問題;部分應(yīng)答碼重點監(jiān)控获洲,通過設(shè)定告警閥值阱表,超過閥值短信及電話告警,研發(fā)第一時間接入處理贡珊,減少可能造成的損失
- 郵件巡檢報告:用于第二天研發(fā)自助數(shù)據(jù)分析
5 規(guī)劃
動態(tài)分片:包括數(shù)據(jù)分片捶枢、任務(wù)分片,業(yè)務(wù)量持續(xù)倍數(shù)增長情況飞崖,各環(huán)節(jié)分片策略如何做到自動化,充分壓榨各機器性能
智能路由:遇到渠道異常谨胞、臨時停用渠道等case固歪,需將用戶切換至其他渠道,當下是人工拉數(shù)據(jù)手工操作胯努,后續(xù)思考如何讓路由更智能
全鏈路的監(jiān)控:我們現(xiàn)在鏈路監(jiān)控只是從前端到后端有一個請求的跟蹤號牢裳,但是這個都分散在我們業(yè)務(wù)日志里面的。所以說我們下一步就準備做一個全鏈路的監(jiān)控叶沛,就相當于把每一個每筆交易蒲讯,它具體在哪個時間點在哪個機器上,然后在哪個渠道灰署,然后它狀態(tài)做的什么變更判帮,做一個完整的記錄局嘁,通過一個可視化的界面提供出來,方便客服晦墙、運營等其他協(xié)作部門使用
獲取更多干貨內(nèi)容悦昵,記得關(guān)注我哦。
本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布晌畅!