閱讀415 返回首頁    go 京東網上商城


從架構到監控報警,支付係統的設計如何步步為營

企業所處發展階段不同,對支付係統的定位和架構也不盡相同。整體上來說,我們可以把一個公司的支付係統發展分為三個階段:

 

  1. 支付係統:支付作為一個(封閉)的、獨立的應用係統,為各係統提供支付功能支持。一般來說,這個係統僅限於為公司內部的業務提供支付支持,並且和業務緊密耦合。

  2. 支付服務:支付作為一個開發的係統,為公司內外部係統、各種業務提供支付服務。支付服務本身應該是和具體的業務解耦合的。

  3. 支付平台:支付作為一個可擴展的平台, 公司內外部的用戶可以在此基礎上定製開發自己的服務。

 

這個劃分有點勉強。簡單說,支付係統是僅供內部使用的,支付服務是支持公司內外部來調用的,支付平台是可以在服務的基礎上定製各種場景支持的。

 

一、支付係統架構 

 

 1、支付業務流程 

 

區分兩個概念:支付和交易。支付是交易的一部分。一個簡單的交易過程包括:客戶下訂單,客戶完成支付,商家接收訂單,商家出貨。這裏僅考慮下訂單的流程。從軟件工程的角度, 我們首先需要明確下幾個參與者。

 

  • 電商係統,指提供在線購物服務的係統。用戶在這個係統中完成交易。

  • 支付係統,可以是電商係統的一個模塊,或者是個獨立的係統。這是本文的主角,用來完成支付過程。

  • 用戶,在電商係統中敗家的那位。如果使用銀行卡做交易,那也被稱為持卡人。

  • 用戶使用銀行卡交易時,發行這個銀行卡的機構稱為發卡行,或者發卡機構。

  • 商家也需要一張卡,就是大家在淘寶開網店的時候要登記的銀行卡,最終需要把用戶給的錢打到這張卡上。

  • 和發卡機構相對應的,大家聽到最多的是收單機構。如支付寶,微信等第三方支付公司,介紹業務的時候總少不了互聯網收單的工作。它們把用戶訂單收起來,找發卡行要錢,就有了收單業務。

 

主演都有了,下麵就是如何演出支付這場大戲了。正常的流程應該是這樣:

 

1、用戶提交訂單到電商係統,電商係統對訂單進行檢驗,無問題則調起支付接口執行支付。注意這裏支付接口是在服務器端調起的。一般支付接口很少從客戶端直接調起。為了安全,支付接口一般要求用HTTPS來訪問,並對接口做簽名。關於支付接口的設計,我將另起博文介紹。

 

2、支付係統檢查參數有效性,特別是簽名的有效性。

 

3、根據用戶選擇的支付方式,以及係統支付路由設置,選擇合適的收單機構。這裏涉及三個概念,支付方式,支付路由。這又是一個槽點。簡單說,用戶可以選擇各種銀行卡支付,比如寧波銀行卡,但是你的支付係統沒有對接寧波銀行,那對這種卡,可以選擇你接入的,支持這個卡的收單機構來執行支付,如用微信或者支付寶等等第三方支付,或者銀聯支付等係統支持的方式來執行。這就是支付路由,根據用戶提供的銀行卡來選擇合適的收單機構去執行支付。常用支付方式還包括第三方支付,如微信支付寶等,這種情況下就不需要支付路由了。

 

4、調用收單接口執行支付。這是支付係統的核心。每個公司的收單接口都不一樣,接入一兩個收單機構還好,接入的多了,如何統一這些接口,就是一個設計難點。

 

5、支付成功,收單機構把錢打到商戶的賬戶上了。 商家就準備發貨了。 怎麼發貨,不是本文的重點。 這裏關注的要點是, 商家能收到多少錢? 比如100塊錢的商品,用戶支付了100塊錢(運費、打折等另算),這100塊錢,還要刨去電商係統的傭金、支付通道的手續費,才能最終落到商家手裏。

 

這是個Happy流程,一切看起來都很美好,但實際上步步都是坑,一旦有地方考慮不周全,輕者掉單頻發,重者接口被盜刷,損失慘重。

 

如何避免攻擊者修改支付接口參數, 比如100塊錢的東西,改成10塊錢?

 

調用收單接口來執行最終實際支付時,如果支付失敗了,比如卡上沒錢了,怎麼辦?

 

收單接口把賬戶上的錢扣走了,但是通知支付係統的時候出錯了(比如網絡閃斷,或者支付係統重啟了),支付係統不知道這筆交易已經達成了,怎麼處理?

 

還有好多問題……

 

和錢打交道,在任何公司,都跑不掉財務部門。 那財務部門會關注哪些內容? 當然,最重要的是賬務信息。 所有的交易都要記賬,按要求公司都需要定期做審計,每一筆帳都不能出錯。這當然不能等到審計的時候再去核對,而是每天都需要對賬,確保所有的交易支出相抵,也就是所說的把賬給平了。 這就有三種情況: 電商係統和商家對賬;電商係統和支付係統對賬;支付係統和收單機構對賬。作為支付係統,我們僅關注後兩者的情況。

 

從軟件開發角度, 還有一些非功能性需求需要實現:

 

  • 性能: 特別是秒殺的時候,如何滿足高頻率的支付需求?

  • 可靠性:不用說,係統能達到幾個9,是衡量軟件設計功力的重要指標。 99%是基礎, 99.999%是目標,更多的9那就是神了。

  • 易用性:支付中多一個步驟,就會流失至少2%的用戶。 產品經理都在削尖腦袋想想怎麼讓用戶趕緊掏錢。

  • 可擴展性: 近年來支付業務創新產品多,一元購、紅包、打賞等,還有各種的支付場景。 怎麼能夠快速滿足產品經理的需求,盡快上線來搶占市場,可擴展性對支付係統設計也是一個挑戰。

  • 可伸縮性:為了支持公司業務,搞一些促銷活動是必須的。 那促銷帶來的爆發流量,最佳應對方法就是加機器了。 平時流量低,用不了那麼多機器,該釋放的就釋放掉了, 給公司省點錢。

 

 2、支付的典型架構 

 

所以支付的坑還不少,我們先看看互聯網的頭牌們是如何設計支付係統的? 先看看某團的:

 

20161122110415545.jpg

 

再看某Q旅遊公司的:

 

20161122110529582.jpg
對比下某東金融的:

 

20161122110547340.jpg

 

最後看看業界最強的某金服金融的:

 

20161122110555538.jpg
 

整體上來說, 從分層的角度,支付係統和普通的業務係統並沒有本質的區別,也是應用、服務、接口、引擎、存儲等分層。 在應用層,支付係統一般會提供如下子係統:

 

  • 支付應用和產品(應用層): 這是針對各端(PC Web端、android、IOS)的應用和產品。 為各個業務係統提供收銀台支持,同時支付作為一個獨立的模塊,可以提供諸如銀行卡管理、理財、零錢、虛擬幣管理、交易記錄查閱、卡券等功能;

  • 支付運營係統(應用層): 支付係統從安全的角度來說,有一個重要的要求是,懂代碼的不碰線上,管運營的不碰代碼。這對運營係統的要求就很高,要求基本上所有線上的問題,都可以通過運營係統來解決。

  • 支付BI係統(應用層): 支付中產生大量的數據,對這些數據進行分析, 有助於公司老板們了解運營狀況,進行決策支持。

  • 風控係統(應用層):這是合規要求的風險控製、反洗錢合規等。

  • 信用信息管理係統(應用層):用來支持對信用算法做配置,對用戶的信用信息做管理。

 

其他各層功能:

 

  1. 支付服務層:為上述各端係統提供API。這些API也可以提供給業務係統直接使用。

  2. 接口層:和各相關係統對接的接口,其中最重要的是和支付渠道對接的支付網關。

  3. 引擎層: 包括統計分析、風控、反洗錢、信用評估等在後台運行的各個係統。

  4.  存儲層: 各種持久化的數據庫支持。

 

這其實也是普通互聯網應用係統架構,沒有什麼特別之處。比如微服務如何體現,如何滿足性能需求等,在這個視圖中無法體現出來。這隻是個軟件角度的高層視圖,後續我們對各個主要模塊進行分解,從分解視圖中可以知道如何滿足非功能性需求。

 

二、支付係統的監控與報警 

 

關於監控,在各個技術網站,幾乎都是一搜一大把。幾個大的互聯網公司,也都有開發自己的監控係統。 關於這方麵也有不少分享。 這裏介紹針對支付係統的監控和報警,但大部分內容,應該來說,對其他係統也是通用的 。

 

現在基本上Zabbix成為監控的標配了。 一個常規的Zabbix監控實現, 是在被監控的機器上部署Zabbix Agent,從日誌中收集所需要的數據,分析出監控指標,發送到zabbix服務器上。!zabbix監控這種方式要求每個機器上部署Zabbix客戶端,並配置數據收集腳本。Zabbix的部署可以作為必裝軟件隨操作係統一起安裝。

 

 1、係統監控 

 

先說相對比較簡單的係統監控,一般係統監控關注如下指標:

 

  • CPU負載

  • 內存使用率

  • 磁盤使用率

  • 網絡帶寬占用

 

這些指標在Zabbix agent中會提供默認實現,通過簡單配置即可激活。裝機時可以考慮統一配置這些監控。

 

 2、JVM監控 

 

JMX提供了關於JVM的大部分核心信息,啟動時設置參數,支持遠程訪問JMX,之後即可通過接入JMX來實時讀取JVM的CPU、內存等信息。Zabbix也支持通過JMX來獲取信息。

 

 3、服務監控 

 

服務監控主要指接口的狀態監控。 服務監控關注如下指標:

 

  • QPS:每秒請求數 對於使用容器的係統,包括Apache Tomcat,Resin,JBoss等,可以從Access Log中采集到每個接口的QPS。沒輸出Access Log的係統,考慮通過Annotation來規範輸出訪問計數。當然,這個指標還可以細分為 每秒成功請求數、失敗請求數、總請求數等。

  • 請求響應時間:在服務器端監控每個接口的響應時間。簡單做法是在方法執行前後打時間戳計算,對於HTTP請求,也可以從access log中獲取接口執行時間。當然也可以用annotation來實現統一的執行時間監控。

  • 執行異常數:指程序運行過程中發生的未捕獲處理的異常,一般是對場景考慮不周導致的異常發生,比如空指針、錯誤參數、數據訪問等的異常。 這些異常一旦發現,需要修複代碼邏輯。 異常在應用日誌中一般都會把錯誤堆棧打印出來。

 

 4、數據庫監控 

 

數據庫是大部分應用的核心和瓶頸,對其監控尤其必要。監控可以 在應用側執行,也可以在數據庫服務器上做。前者通過應用代碼中打印日誌來實現,或者直接override 鏈接池中相關方法來統一輸出日誌。在數據庫服務器上執行監控,需要根據數據庫的特點分別設計方案。以MySQL為例,可以通過監控其bin log來獲取執行的sql語句以及執行時間。使用Alibaba Canal 來對接MySQL的BinLog, 接收到BinLog消息後,解析消息數據,可以獲取請求的SQL、參數、執行時間、錯誤代碼等信息。

 

數據庫監控重點關注如下指標:

 

  • 每秒請求數

  • 慢查詢處理數

  • SQL語句執行時間

 

 5、調用鏈監控 

 

調用鏈監控指在微服務係統中,跟蹤一個請求從發起到返回,在各個相關係統中的調用情況。 調用鏈監控是跨係統的監控,需要在請求發起時分配一個可以唯一識別本次調用請求(或者成為事務)的ID,這個ID會被分發到每個調用上。之後在調用日誌中輸出該ID。當所有日誌都匯總起來後,可以從日誌中分析本次調用的流程。 對於HTTP/HTTPS請求,可以考慮將ID放到Header裏麵,這樣不會影響接口邏輯。

 

 6、業務監控 

 

業務監控是一個複雜的話題。這裏以支付為例,說明業務監控的架構和實現。

 

支付業務監控

 

每個支付通道監控包括如下內容:

 

  1. 支付通道接口請求數: 如果一段時間內接口請求環比大幅度下降,可能是該接口出現問題了。

  2. 支付通道接口請求失敗數,即調用接口失敗的數量。

  3. 支付通道接口請求延遲。

  4. 支付通道支付失敗率。每個通道支付有一定的失敗率,如果給定時間內突然有超過這個失敗率的情況出現,則可能是通道出現問題了。

  5. 支付通道同步、異步調用次數。

 

支付接口,如支付、提現、退款、簽約、訂閱等,監控如下內容:

 

  1. 總金額,如果總金額有大的波動,則有洗錢的可能

  2. 每筆平均金額

  3. 支付成功率

 

監控架構

 

實際上對一個業務來說,大部分係統監控的指標是類似的,而按照這種方式,每個指標在各個被監控係統中還需要單獨寫腳本實現,工作量大。針對這種情況,可以采用日誌集中監控的方式來處理。 考慮到日誌最終都需要歸並到一個日誌倉庫中,這個倉庫可以有很多用途,特別是日常維護中的日誌查詢工作。多數指標可以在日誌上完成計算的。 借助這個係統,也可以完成監控: !zabbix 監控

 

日誌通過Apache Flume來收集,通過Apache Kafka來匯總,一般最後日誌都歸檔到Elastic中。 統計分析工作也可以基於Elastic來做,但這個不推薦。 使用Apache Spark 的 Streaming組件來接入Apache Kafka 完成監控指標的提取和計算,將結果推送到Zabbix服務器上,就可以實現可擴展的監控。 

 

這個架構的優勢在於:

 

  • 監控腳本的跨係統使用。 指定日誌規範後, 隻要按照這個規範編製的日誌,都可以納入監控,無需額外配置。

  • 服務重新部署時無須考慮監控腳本的部署,所有監控直接生效。

 

難點在於,提煉一套通用的日誌規範,考慮如何通過Spark來分析日誌。

 

日誌收集

 

Flume和logstash都可以用於日誌收集,從實際使用來看,兩者在性能上並無太大差異。flume是java係統,logstash是ruby係統。使用中都會涉及到對係統的擴展,這就看那個語言你能hold住了。

 

日誌數據流

 

Flume和Logstash都支持日誌直接入庫,即寫入HDFS,Elastic等,有必要中間加一層Kafka嗎?太有必要了,日誌直接入庫,以後分析就限製於這個庫裏麵了。接入Kafka後,對於需要日誌數據的應用,可以在kafka上做準實時數據流分析,並將結果保存到需要的數據庫中。

 

日誌分析

 

Streaming分析,可以走Spark,也可以用Storm,甚至直接接入kafka做單機處理。這取決於日誌數據規模了。Spark streaming是推薦的,社區活躍度高,又集成了多種算法。

 

日誌係統與日誌框架

 

Java主流的日誌係統有log4j,JULlogback等,日誌框架有apache commons logging,slf等,關於這些係統的曆史掌故恩怨情仇八卦趣事,網上有不少資料,這裏不詳細介紹。

 

日誌係統選型

 

最好的編程語言是PHP還是Java? 同樣的,也有爭論:最好的日誌框架是slf還是commons-logging?最好的日誌係統是Log4j還是Logback?在使用上,它們的API和使用方式大體類似,slf有模版支持,但這也不是關鍵需求。而性能方麵,從我們測試用例中也沒有發現哪個係統或框架有明顯優勢。對性能有決定性影響的是使用方式。

 

日誌高能預警

 

根據我們的測試,在高並發係統中,關於日誌,有如下結論:

 

  • Log4j與logback在高並發下性能上並無太多差異,不用太糾結使用哪個API,.影響性能的是日誌內容的寫法和數據量。

  • 輸出類名和行號會嚴重影響性能,這需要使用到性能不佳的反射機製。執行頻率高,性能要求高的代碼,禁用反射,禁用new操作。

  • 高峰期係統出錯,如果打印錯誤堆棧,那絕對是雪上加霜,理由同上。

  • 多線程時輸出日誌,寫鎖是影響性能的關鍵因素。緩解寫鎖的措施,首選加大日誌寫入緩衝區,其次是異步打印。異步對性能有提升,但不顯著。寫鎖出問題的一個現象是CPU跑滿。

  • 原文發布時間為:2016-11-22 本文來自雲棲社區合作夥伴DBAplus

最後更新:2017-05-11 12:01:24

  上一篇:go  一條會施魔法的MySQL命令: STOP ALL SLAVES
  下一篇:go  MySQL實戰係列3:視圖、存儲過程、函數、索引全解析