成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go語言在掃碼支付系統中的成功實踐

開發 后端
今天的內容主要分四個方面。第一,金融支付系統的一些特點;第二,我們的掃碼支付系統技術選型;第三,系統迭代過程中的架構演進;第四,與Go相關的一些坑。

今天的內容主要分四個方面。***,金融支付系統的一些特點;第二,我們的掃碼支付系統技術選型;第三,系統迭代過程中的架構演進;第四,與Go相關的一些坑。

金融支付系統的一些特點

Go語言在掃碼支付系統中的成功實踐
圖 1

首先從業務流程入手,其實非常簡單。一位消費者結賬時,假如選擇掃碼支付的方式付款 100 元,產生一筆交易信息。如圖 1 所示,我們看上面藍色的線條,通過商家的收款產品,把這 100 元的交易信息送到我們的掃碼支付系統,然后傳遞到后面的微信、支付寶或者其他支持掃碼支付的相應錢包,完成這筆交易信息的傳遞,完成這筆交易處理。

在行業內,通常稱藍色的線條為信息流。信息流是什么意思?就是傳遞這筆交易的信息。接下來, 完成 信息傳遞還沒有結束,看圖中灰色的線條,通常在第二天的時候,即 T+1 時,我們會通過商家的清算銀行把這 100 元清到商戶的清算賬戶,這樣才算完成了這筆資金的清算,因此我們稱下面的灰色線條為資金流。很簡單,我們今天更關注的是上面信息流相關的處理。

接下來,我們看一下信息流相關處理。除了我剛剛提到的,實時交易處理 100 元的信息傳遞外,還會涉及到哪些方面呢?一個是實時交易的服務,另外一個是商戶對賬的服務。剛剛提到資金流的傳遞是商家收到 100 元,那么收到的金額對不對,和前一天交易行為是不是匹配呢?商家需要一些對賬報表,來核對相應交易行為、到賬資金,這就是對賬服務。

另外,其他的一些商戶服務,包括一些商戶信息的維護,商戶交易行為的查詢,交易記錄的查詢方面,最基本來說是這三類的服務。另外,可能會有更多附加的服務,包括風控,以及其他的一些增值營銷服務等。

今天,我們聚焦在這三類基本服務,看看三類基本服務對應的后臺系統的類型是什么樣子。

首先是實時交易服務:API Gateway?;氐絼倓?100 元的處理,從商家收款產品,到我們掃碼交易的處理系統,接口過來以后,在系統中進行一些相應的業務邏輯處理,交易信息落地,之后把交易信息分發到后面相應的接口。整個流程,實際上無非就是接口的轉換,中間攙雜一些相應的業務處理。跟我們微服務架構上的 API Gateway 的定位其實非常類似,可以理解為它就是一個加入了一些業務邏輯的 API Gateway 系統。從商家對賬服務來說,通常是在交易發生的第二天進行資金流的流轉,與之同步的會有相應的對賬報表要給到商家,為商家提供對賬服務。通常來說,對賬服務會涉及到批處理相應系統。商戶服務剛才提到的查詢、信息維護等,這些可能是相應的 web portal 提供相應的商戶服務。

從業務角度出發 , 對我們的系統有什么基本的要求?

***,既然是支付系統,安全性肯定是再怎么強調也不為過的;

第二,穩定性也是一個必不可少要考慮的關鍵點。包括我們的商家可能會有各種類型的客戶,包括餐館可能白天營業,夜店可能半夜也會有交易發生。整個系統 7*24 小時的穩定性,也是需要考慮的重點;

第三,我們系統的吞吐量,這個就很好理解了,當前面的客戶、商家交易量上來的時候,整個系統包括并發處理能力,請求的響應時間等,都是業務上非常關注的重點。

回到最開始提到的問題,我們用 Golang 來搭建支付處理系統,靠不靠譜。 在我理解就是這三方面的考量:安全性有沒有保證,穩定性是不是足夠穩定,吞吐量是不是能夠達到業務的要求。接下來看看到底能還是不能,進入技術選型話題。

技術選型

從技術選型來說,剛才提到的三個方面,主要是業務需求方面的考量。業務需求方面,在 2015 年, 我們 搭建這套系統的時候,還有另一點非常重要的考量。因為 2015 年正好是掃碼支付方式快速發展的階段,當時,業務方面對于系統的快速迭代要求是非常高的。技術選型方面,除了業務需求,還有技術需求和團隊需求。技術需求是什么意思?我們知道在軟件開發領域,有一句話 叫 “沒有銀彈” , 不能拿起錘子當什么都是釘子,每一門技術都有它適用的場景和范圍。剛才幾個系統,幾個服務類型顯然都是 Golang 所擅長的范圍,這是技術需求的角度。

團隊需求是什么含義呢?想跟大家分享一個故事。前兩年,我朋友的一家公司有一個網站,網站***個版本是請外包團隊實現的,拿到驗收發現很不錯,使用的是"世界上***的語言"。然而問題來了,當這家公司拿到***期交付成果以后,想要自己接過來,在上面疊加一些功能進行版本的迭代。結果發現團隊里沒有會"***語言"的成員,出于種種原因既沒有從外部招到,也沒有從內部培養起來。結果是他們又花了幾個月,用另一門語言把這個網站重寫了一遍,這就是我們在團隊需求里面想提到的一點,一門技術不管是編程語言還是系統組件,要引入這門技術,首先團隊里要有人會這門技術。另一點也是通常會比較容易忽略的,就是對于一門技術的引入,除了團隊中有相應的人能夠寫這個代碼,很重要的是,有沒有人能夠 hold 這門技術。在遇到技術難題的時候,有人能夠處理。這門技術在團隊內的培訓時,能夠有帶頭人也是一個非常重要的方面。

從技術選型的角度主要是這三方面的考量,結合我們 2015 年搭建這套系統的現狀來看一下。當時我們團隊的技術棧編程語言方面是 C、Java、Golang。選擇掃碼支付系統實現的語言的時候,C 是***個被我們否決掉的,開發效率就滿足不了我們快速迭代的要求。我們更多的可能是從 Java、Golang 進行權衡。Golang 團隊當時人數并不多,只有三位小伙伴,但是三位小伙伴都是非常不錯的,對 Golang 的理解也很棒。到現在我們回頭來看,從三個人到現在大概有接近兩年時間的發展,我們團隊中現在有 20 多位,超過整個研發團隊一半以上的人數,已經可以熟練的掌握 Golang,用 Golang 來實現我們的業務系統、業務功能, Golang 在我們團隊中的普及發展,也是非常迅速的。團隊背景大概是這樣。

技術需求方面,我們來看 Golang 的技術特點。我這里簡單列舉一些對我們感受比較深刻的方面:

***,快速上手,學習曲線平滑,開發效率非常高。我們團隊發展歷程可以充分證明這一點,從三位 Golang 小伙伴到二十多位,一年多不到兩年的時間,大多數是從內部轉型過來的,不管是 C 還是 Java 轉型過來小伙伴,大家轉型和上手過程的普遍感受都是學習起來沒有什么困難,上手非???,開發效率方面也非常不錯。在 2015 年最初搭建這套系統的時候,行業市場瞬息萬變,甚至不夸張的說, 當時這個系統 一天一個版本,開發效率非常高;

第二,天生支持并發編程,對于我們后端普遍需要并發處理的場景也是非常適合的;

第三,簡潔的錯誤處理: panic、recover、defer 。有人可能會喜歡,有人可能會不太習慣,我個人很習慣這樣的處理方式。這塊我們也遇到一些問題,踩過一些坑,這個在***會跟大家分享。

剛剛是團隊需求、技術需求方面。接下來我們更關注業務需求方面。我們剛才提到三點:

***,安全性。從安全性角度出發為什么選擇 Golang?選擇 Golang 靠不靠譜?一個支付系統,它的整個處理流程的安全性,實際上涉及到方方面面,包括數據傳輸的安全性,是否有數據泄露的風險,是否有防篡改的措施;數據落地存儲的時候,存儲是不是關鍵信息有做加密;網絡方面,網絡是不是有接入層、防火墻等等。整個系統的安全性,從接入層到應用層、系統組件,再到 Database,每一層可能都會有相應安全性方面的考量。落地到編程語言選擇,Golang 的安全性靠不靠譜呢?編程語言的安全性更關注什么呢?很自然的想到一點就是語言的漏洞。

Go語言在掃碼支付系統中的成功實踐
圖 2

關于漏洞,我們將收集到一個數據和大家分享一下,如圖 2 所示是一個漏洞搜集的網站,我用關鍵詞 Golang 搜索漏洞,可以看到五個,然后用關鍵詞 Java 搜索,有 1660 個。沒有黑 Java 的意思,解釋一下這 1000 多個是什么意思:畢竟 Java 發展這么多年已經非常成熟,JDK 的漏洞其實非常少了,1000 多個絕大多數都是各種框架的漏洞。例如我們一些存量系統,有的 web 平臺用的 ssh 框架,眾所周知的"萬年漏洞王"迫使我們每年都要對這套框架進行一次升級。反過來看 Golang,一方面是因為 Golang 比較新,曝出來的漏洞沒有那么多;另一方面,Golang 的安全性也確實沒有遇到過什么問題。而且 Golang 背靠 Google,有龐大的社區。所以從編程語言的安全性方面考慮的話,在我們看來選擇 Golang 沒有必要顧慮太多,這是安全性方面。

第二,穩定性。其實和安全性類似的一點是,同樣需要考量在系統整體架構,系統各個層級等方面的穩定性。昨天下午 B 站的老師也跟大家分享了微服務演進過程中,系統穩定性方面的考量,限流、容錯、故障隔離等。系統的接入層限流是不是足夠好,應用層是不是高可用,緩存、數據庫等組件也都需要有穩定性方面相應的考量。同樣,落地到我們的編程語言應用實現方面,在穩定性上更關注的是什么內容呢?在我們看來,應用高可用架構,即應用的實現要做到無狀態,支持橫向擴展。其實這一點,不管是 Golang 還是 Java 還是其他的語言,只要結構、代碼設計的好, 做到這一點 沒有什么壓力。

第三,吞吐量。隨著業務發展,交易量逐步增加,客戶越來越多,吞吐量是否得到很好的支撐?在這方面,準備了兩個并發處理能力方面的例子。這兩個也是我們系統中會經常用到的功能。一個是 http 接口的并發處理能力, 另外一個是 RSA 加解密的例子。

Go語言在掃碼支付系統中的成功實踐
圖 3

如圖 3 所示是我的實驗環境,是用自己的 MacBook,雙核 8G 的環境,Golang 是 1.7 的版本。同時為了有一個對標的效果,單獨拿 Golang 看它的效率可能看不出什么,因此拿 Java 做了一個對標,再強調一遍, 只是一個對標的目的, 沒有黑 Java 的意思。

Go語言在掃碼支付系統中的成功實踐
圖 4

如圖 4 所示,我們來看***個http 接口,這是 Golang 版本非常簡單的 http 接口,這個不用多說,大家看一眼也知道,十幾行的代碼,啟動一個 http 服務,收到一個請求以后,應答,回十個字節,這是 Golang 的版本。Java 版本做的事情是一樣,但是 Java 代碼比較多,沒有截全,因為 Java 的 http 本身沒有帶多線程的方式,寫了一個簡單的線程池,用多線程的方式去處理 http 的請求。

接下來是測試的結果,十個用戶一萬個請求進行測試。上面是一個 Golang 的結果,吞吐量 12000 多,請求 響應 時間是 0.815 毫秒。下面是 Java 版本,吞吐量是 11000 多,響應時間是0.891 毫秒,這兩個版本差別不大,非常相近。從 http 接口方面來說,Java 和 Golang 的處理結果相差不是很大。

下一個例子是 RSA 加解密處理。上面是 Golang 的版本,也是采用并發處理的方式,循環 1000 次,每次進行一次加密、一次解密,加密的密鑰用 2048 byte 長 度的密鑰,待加密的數據是 245 byte。下面是 Java 的版本,也是截了一部分出來,實現方式和 Golang 實現方式一樣。

Go語言在掃碼支付系統中的成功實踐
圖 5

我們直接看結果,如圖 5 所示,上面是 Golang 的結果,下面是 Java 的結果, 用 的是 Mac 自帶的 time 命令來統計耗時。Golang 的結果,程序實際執行時間(real time)是 2.78 秒 ,J ava 執行時間是 7.74 秒,這里會看到三倍左右的差距。這個只能說明在 RSA 加解密處理的簡單場景上面,使用各自的標準庫,可能 Golang 的效率會比 Java 實現 效率 更高一些。當然大家也可以很容易的找出一些反例,在某些場景,Java 比 Golang 的實現效率更高一些。什么意思呢?從不同的場景,不同語言的實現效率或者好一些或者壞一些。對于我們選擇 Golang 來說,只要我們證明它在 我們常用的一些場景 效率沒有問題,我們就可以用 Golang 來做這套系統 。

實際上我們對于 Golang 的吞吐量方面的信心,一方面源于我們的測試結果,另一方面其實在我們搭建這套掃碼支付系統之前,我們還使用 Golang 做過另一個秒殺系統。這個秒殺系統***個版本是使用 Java 來做擋板服務器,但是,可能是我們參數調優沒有做好,在壓力測試的時候,單臺壓到 500 tps 就上不去了。但由于時間緊任務重,沒有來得及做仔細的參數調優,我們換成用 Golang 試了試。結果一晚上的開發時間,輕松幾萬上去沒有什么問題。這也使得我們在 Golang 吞吐量方面建立了很強的信心。

從業務需求角度考慮,不管是安全性、穩定性、吞吐量,選擇 Golang 都沒有什么壓力。

***總結一下,我們最終選擇 Golang 的出發點:作為需要快速原型、快速迭代的項目,需要的開發效率非常高,在滿足當前和未來可預期的高可用、吞吐量等業務需求的前提下, Golang 的高效開發效率,簡單部署和運維,是我們擁抱 Golang 的主要原因。

以上是整個技術選型方面的考量 關鍵點, 多說一句,剛才多次提到系統的吞吐量、高可用的關鍵點,其實除了編程語言這一層,更多的可能跟整體的系統架構有很大關系,當然這是另一個話題了。

架構演進

Go語言在掃碼支付系統中的成功實踐
圖 6

我們來一起看一下系統架構演進的過程。 如圖 6 所示, 是 2015 年上線的***個掃碼交易處理系統。當時整個后臺系統非常簡單。因為當時需要版本快速迭代,而且我們更多的主要力量在為商家提供的收款產品。我們可以看到各種各樣的收款產品,包括云收銀的產品系列,iOS、安卓的 APP,SDK,包括 PC 端的商業軟件,右上角的智能 POS 系列產品等。最初上線的時候,需要利用這些產品快速鋪開前端市場,所以在后臺系統上,是一個非常簡單的架構。系統在上線之后的一段時間,其實還是相對穩定的,畢竟越簡單越穩定。但是隨著業務量的增加,以及業務上需要疊加的功能越來越多,這樣的一個單體應用結構很明顯是撐不住的。所以,接下來我們進行了一系列的架構調整、演進。

Go語言在掃碼支付系統中的成功實踐
圖 7

如圖 7 所示的架構是我們幾個月之前的系統結構,比***個版本復雜很多。主要的掃碼處理系統是在圖左。我們看應用層,從一個單體應用延伸出了多個,包括我們剛剛提到的不同類型的服務:掃碼網關的實時交易處理服務,為商戶提供對賬報表的 批處理的服務 ,為商戶提供信息查詢的 平臺服務。 另外還搭建了我們的風控系統,因為風控在整個支付交易處理中也是非常重要的方面。APP 后臺,是我們 iOS、安卓的 App 提供的單獨的后臺服務。整個這一套系統,都是 使用 Golang 實現的。Golang 在統一系統實現的技術棧方面,為我們提供了很大的幫助 。 中間件方面 ,為了 解耦和提高穩定性, 我們引入了kafka、redis等系統組件。 為了實現跨機房災備系統搭建,我們自研了一套數據庫的同步工具,可以從 MongoDB 文檔型的數據庫,將數據實時同步到 MongoDB 或者 MySQL 等其他關系型數據庫,這套工具也是使用 Golang 來做的。

在整個架構的完善方面,根據業務職能拆出更多的系統。目前我們的系統在此基礎之上,進行了更多的一些往服務化方面的逐步演進,這是整個系統架構演進的過程。

一些坑

Go語言在掃碼支付系統中的成功實踐
圖 8

如圖 8 所示,很簡單的 十幾行代碼,它提供的是 TCP 長連接服務端的服務。每 accept 一條鏈接,收到客戶端的請求之后,開一個 goroutine,通過 handleConnection 這個函數進行客戶端連接的處理。針對 handleConnection 這個函數進行了一層包裝,稱之為 TcpRecoverWrap,包裝里做了什么,看名字也知道,是一個 recover 的包裝,具體的實現在圖右,非常簡單,也是 Golang 里面比較常用的處理方式,給一個函數加一個包裝,包裝里面加一個 defer 進行 recover 處理。

Go語言在掃碼支付系統中的成功實踐
圖 9

這段代碼看起來很簡單,那么問題來 了 ,是不是在 handleConnection 函數內發生的任何 panic 都能通過 TcpRecoverWrap 這樣的實現方式來解決?既然提出這個問題,答案肯定是否定的。來看一下 handleConnection 的具體 實現,如圖 9 右邊所示,是一個 TCP 的服務端,已經 accept 一個鏈接,開始 read,在一個死循環里面進行 read 操作,每 read 一條客戶端發來的請求信息,開一個 goroutine 進行實際的業務處理,把讀到的消息給到業務處理的函數,當業務處理完成,拿到業務處理結果以后,把結果寫到一個 channel 里面,這個結果由另一個 goroutine 來接收,接收到以后把應答的消息回復給 TCP 客戶端,也是很簡單的一段代碼。

我們剛才列出來的兩個問題,全都在這一段代碼里面了。***個變量作用域,第二個 chan 操作。這幾十行代碼里,哪一個變量作用域存在問題?右上角的 reqBytes 的變量,我們看到前面在 for 循環外面定義了一個 reqBytes,接下來進入到循環中,每一次讀到的東西都放到 reqBytes,我們可以看到,其實每次循環,使用的 reqBytes 是一個變量,它的內存空間是一個。那么問題來了, goroutine 開啟方式是一個必包的方式, 外面的變量對于每個子 goroutine 來說是可見的,也就是每讀到一條消息,放到同樣一個變量里面,有可能的結果是,***個消息開了一個 goro u tine,但這個 goroutine 還沒來得及調度的時候,又收到到第二個消息,那么第二個消息會把***個 goroutine 里面的消息覆蓋,不同請求之間會產生關聯影響。

第二個 chan 操作問題。我們知道在寫 chan 的時候,如果 chan 已經被關了,那么對它進行寫入操作會 panic。我們看圖9中的 writeMsgQueue 這個 chan ,在 defer 里面進行了關閉。當這個 TCP 連接不可用的時候, handleConnection 函數 return 之前關閉這個 chan,目的是 chan 關閉后,通過檢查 chan 狀態,可以促使 goroutine 退出,避免 goroutine 泄露,但是這個 defer 的 close 引入了另一個問題,如果服務端收到消息、開 goroutine 進行業務處理的過程中,客戶端已經斷開了連接,那么此時 chan 已經關閉了,當服務端業務處理完成的時候,寫入一個已關閉的 chan ,就會panic。更可怕的是,這個 panic 是不能被 TcpRecoverWrap 包裝的,因為在執行 defer 結束、關閉了chan 之后,handleConnection 函數就已經 return,也就是這個 panic 是發生在另一個 goroutine 的,和 handleConnection 函數沒有關系,很顯然剛才的包裝方式是沒有辦法捕捉這樣的 panic 進行 recover 的。

Go語言在掃碼支付系統中的成功實踐
圖 10

今天分享的內容大概就是這些,那么怎么修這些問題呢?很簡單,變量作用域拿到 for 循環里面,panic 的問題可以加另外一個 tcp 關閉信號,通過這樣的方式,來修復剛才說的兩個問題。當然修復方式可能有很多種,僅供大家參考。

責任編輯:未麗燕 來源: 推酷
相關推薦

2019-01-15 09:10:17

邊緣計算數據中心IT

2019-01-16 10:33:41

Linux

2010-06-25 19:07:38

SAP

2014-09-01 09:57:11

Go產品環境最佳語言

2020-04-20 11:09:30

DevOps實踐因素

2021-08-19 08:04:36

IT部門首席信息官CIO

2023-12-18 09:58:46

微信掃碼支付Vue3

2018-11-23 14:00:43

AI支付寶刷手

2022-10-30 23:13:30

contextGo語言

2022-04-18 09:41:14

Go架構設計

2023-10-11 07:20:17

2021-11-30 07:31:42

微信支付寶付款

2023-12-13 07:19:01

微服務架構Golang

2011-09-30 13:54:10

H3C云網絡云安全

2018-04-08 15:33:37

移動支付支會寶微信

2021-04-26 22:17:48

計算

2021-10-19 09:46:22

ReactGo 技術

2019-05-21 15:15:22

掃碼乘車公交卡支付方式

2017-12-18 18:23:09

支付寶掃碼賺錢支付寶套路
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品精品视频一区二区三区 | 亚洲日韩第一页 | 国产乱人伦 | 韩日三级 | 国产精品欧美一区二区三区不卡 | 国产91丝袜在线18 | 久久91精品久久久久久9鸭 | 中文字幕一区二区三区四区五区 | 国产伦一区二区三区 | 精品九九 | 欧美国产日韩在线观看成人 | 国产一区二区三区不卡av | 综合色在线 | 日韩免费看片 | 欧洲精品码一区二区三区免费看 | av黄色在线播放 | 视频在线h| 9999视频| 中文字幕日韩一区 | 成人3d动漫一区二区三区91 | 日韩免费视频 | 天天在线操| 黄色片在线看 | 久久一日本道色综合久久 | 91精品国产91久久久久久吃药 | 99久久久久久 | 91社区视频 | 国产高清视频在线观看播放 | 91在线视频免费观看 | 精品久久99| 天天躁人人躁人人躁狂躁 | 99精品国产一区二区三区 | 992tv人人草| 亚洲欧美一区二区三区国产精品 | 国产精品一区二区三级 | 国产成人精品综合 | 一区二区三区视频 | 成人午夜精品一区二区三区 | 国产一区二区三区免费视频 | 久久九九99 | 九九热免费视频在线观看 |