偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐

開(kāi)發(fā) 后端
今天的內(nèi)容主要分四個(gè)方面。第一,金融支付系統(tǒng)的一些特點(diǎn);第二,我們的掃碼支付系統(tǒng)技術(shù)選型;第三,系統(tǒng)迭代過(guò)程中的架構(gòu)演進(jìn);第四,與Go相關(guān)的一些坑。

今天的內(nèi)容主要分四個(gè)方面。***,金融支付系統(tǒng)的一些特點(diǎn);第二,我們的掃碼支付系統(tǒng)技術(shù)選型;第三,系統(tǒng)迭代過(guò)程中的架構(gòu)演進(jìn);第四,與Go相關(guān)的一些坑。

金融支付系統(tǒng)的一些特點(diǎn)

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 1

首先從業(yè)務(wù)流程入手,其實(shí)非常簡(jiǎn)單。一位消費(fèi)者結(jié)賬時(shí),假如選擇掃碼支付的方式付款 100 元,產(chǎn)生一筆交易信息。如圖 1 所示,我們看上面藍(lán)色的線條,通過(guò)商家的收款產(chǎn)品,把這 100 元的交易信息送到我們的掃碼支付系統(tǒng),然后傳遞到后面的微信、支付寶或者其他支持掃碼支付的相應(yīng)錢包,完成這筆交易信息的傳遞,完成這筆交易處理。

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

接下來(lái),我們看一下信息流相關(guān)處理。除了我剛剛提到的,實(shí)時(shí)交易處理 100 元的信息傳遞外,還會(huì)涉及到哪些方面呢?一個(gè)是實(shí)時(shí)交易的服務(wù),另外一個(gè)是商戶對(duì)賬的服務(wù)。剛剛提到資金流的傳遞是商家收到 100 元,那么收到的金額對(duì)不對(duì),和前一天交易行為是不是匹配呢?商家需要一些對(duì)賬報(bào)表,來(lái)核對(duì)相應(yīng)交易行為、到賬資金,這就是對(duì)賬服務(wù)。

另外,其他的一些商戶服務(wù),包括一些商戶信息的維護(hù),商戶交易行為的查詢,交易記錄的查詢方面,最基本來(lái)說(shuō)是這三類的服務(wù)。另外,可能會(huì)有更多附加的服務(wù),包括風(fēng)控,以及其他的一些增值營(yíng)銷服務(wù)等。

今天,我們聚焦在這三類基本服務(wù),看看三類基本服務(wù)對(duì)應(yīng)的后臺(tái)系統(tǒng)的類型是什么樣子。

首先是實(shí)時(shí)交易服務(wù):API Gateway。回到剛剛 100 元的處理,從商家收款產(chǎn)品,到我們掃碼交易的處理系統(tǒng),接口過(guò)來(lái)以后,在系統(tǒng)中進(jìn)行一些相應(yīng)的業(yè)務(wù)邏輯處理,交易信息落地,之后把交易信息分發(fā)到后面相應(yīng)的接口。整個(gè)流程,實(shí)際上無(wú)非就是接口的轉(zhuǎn)換,中間攙雜一些相應(yīng)的業(yè)務(wù)處理。跟我們微服務(wù)架構(gòu)上的 API Gateway 的定位其實(shí)非常類似,可以理解為它就是一個(gè)加入了一些業(yè)務(wù)邏輯的 API Gateway 系統(tǒng)。從商家對(duì)賬服務(wù)來(lái)說(shuō),通常是在交易發(fā)生的第二天進(jìn)行資金流的流轉(zhuǎn),與之同步的會(huì)有相應(yīng)的對(duì)賬報(bào)表要給到商家,為商家提供對(duì)賬服務(wù)。通常來(lái)說(shuō),對(duì)賬服務(wù)會(huì)涉及到批處理相應(yīng)系統(tǒng)。商戶服務(wù)剛才提到的查詢、信息維護(hù)等,這些可能是相應(yīng)的 web portal 提供相應(yīng)的商戶服務(wù)。

從業(yè)務(wù)角度出發(fā) , 對(duì)我們的系統(tǒng)有什么基本的要求?

***,既然是支付系統(tǒng),安全性肯定是再怎么強(qiáng)調(diào)也不為過(guò)的;

第二,穩(wěn)定性也是一個(gè)必不可少要考慮的關(guān)鍵點(diǎn)。包括我們的商家可能會(huì)有各種類型的客戶,包括餐館可能白天營(yíng)業(yè),夜店可能半夜也會(huì)有交易發(fā)生。整個(gè)系統(tǒng) 7*24 小時(shí)的穩(wěn)定性,也是需要考慮的重點(diǎn);

第三,我們系統(tǒng)的吞吐量,這個(gè)就很好理解了,當(dāng)前面的客戶、商家交易量上來(lái)的時(shí)候,整個(gè)系統(tǒng)包括并發(fā)處理能力,請(qǐng)求的響應(yīng)時(shí)間等,都是業(yè)務(wù)上非常關(guān)注的重點(diǎn)。

回到最開(kāi)始提到的問(wèn)題,我們用 Golang 來(lái)搭建支付處理系統(tǒng),靠不靠譜。 在我理解就是這三方面的考量:安全性有沒(méi)有保證,穩(wěn)定性是不是足夠穩(wěn)定,吞吐量是不是能夠達(dá)到業(yè)務(wù)的要求。接下來(lái)看看到底能還是不能,進(jìn)入技術(shù)選型話題。

技術(shù)選型

從技術(shù)選型來(lái)說(shuō),剛才提到的三個(gè)方面,主要是業(yè)務(wù)需求方面的考量。業(yè)務(wù)需求方面,在 2015 年, 我們 搭建這套系統(tǒng)的時(shí)候,還有另一點(diǎn)非常重要的考量。因?yàn)? 2015 年正好是掃碼支付方式快速發(fā)展的階段,當(dāng)時(shí),業(yè)務(wù)方面對(duì)于系統(tǒng)的快速迭代要求是非常高的。技術(shù)選型方面,除了業(yè)務(wù)需求,還有技術(shù)需求和團(tuán)隊(duì)需求。技術(shù)需求是什么意思?我們知道在軟件開(kāi)發(fā)領(lǐng)域,有一句話 叫 “沒(méi)有銀彈” , 不能拿起錘子當(dāng)什么都是釘子,每一門技術(shù)都有它適用的場(chǎng)景和范圍。剛才幾個(gè)系統(tǒng),幾個(gè)服務(wù)類型顯然都是 Golang 所擅長(zhǎng)的范圍,這是技術(shù)需求的角度。

團(tuán)隊(duì)需求是什么含義呢?想跟大家分享一個(gè)故事。前兩年,我朋友的一家公司有一個(gè)網(wǎng)站,網(wǎng)站***個(gè)版本是請(qǐng)外包團(tuán)隊(duì)實(shí)現(xiàn)的,拿到驗(yàn)收發(fā)現(xiàn)很不錯(cuò),使用的是"世界上***的語(yǔ)言"。然而問(wèn)題來(lái)了,當(dāng)這家公司拿到***期交付成果以后,想要自己接過(guò)來(lái),在上面疊加一些功能進(jìn)行版本的迭代。結(jié)果發(fā)現(xiàn)團(tuán)隊(duì)里沒(méi)有會(huì)"***語(yǔ)言"的成員,出于種種原因既沒(méi)有從外部招到,也沒(méi)有從內(nèi)部培養(yǎng)起來(lái)。結(jié)果是他們又花了幾個(gè)月,用另一門語(yǔ)言把這個(gè)網(wǎng)站重寫了一遍,這就是我們?cè)趫F(tuán)隊(duì)需求里面想提到的一點(diǎn),一門技術(shù)不管是編程語(yǔ)言還是系統(tǒng)組件,要引入這門技術(shù),首先團(tuán)隊(duì)里要有人會(huì)這門技術(shù)。另一點(diǎn)也是通常會(huì)比較容易忽略的,就是對(duì)于一門技術(shù)的引入,除了團(tuán)隊(duì)中有相應(yīng)的人能夠?qū)戇@個(gè)代碼,很重要的是,有沒(méi)有人能夠 hold 這門技術(shù)。在遇到技術(shù)難題的時(shí)候,有人能夠處理。這門技術(shù)在團(tuán)隊(duì)內(nèi)的培訓(xùn)時(shí),能夠有帶頭人也是一個(gè)非常重要的方面。

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

技術(shù)需求方面,我們來(lái)看 Golang 的技術(shù)特點(diǎn)。我這里簡(jiǎn)單列舉一些對(duì)我們感受比較深刻的方面:

***,快速上手,學(xué)習(xí)曲線平滑,開(kāi)發(fā)效率非常高。我們團(tuán)隊(duì)發(fā)展歷程可以充分證明這一點(diǎn),從三位 Golang 小伙伴到二十多位,一年多不到兩年的時(shí)間,大多數(shù)是從內(nèi)部轉(zhuǎn)型過(guò)來(lái)的,不管是 C 還是 Java 轉(zhuǎn)型過(guò)來(lái)小伙伴,大家轉(zhuǎn)型和上手過(guò)程的普遍感受都是學(xué)習(xí)起來(lái)沒(méi)有什么困難,上手非??欤_(kāi)發(fā)效率方面也非常不錯(cuò)。在 2015 年最初搭建這套系統(tǒng)的時(shí)候,行業(yè)市場(chǎng)瞬息萬(wàn)變,甚至不夸張的說(shuō), 當(dāng)時(shí)這個(gè)系統(tǒng) 一天一個(gè)版本,開(kāi)發(fā)效率非常高;

第二,天生支持并發(fā)編程,對(duì)于我們后端普遍需要并發(fā)處理的場(chǎng)景也是非常適合的;

第三,簡(jiǎn)潔的錯(cuò)誤處理: panic、recover、defer 。有人可能會(huì)喜歡,有人可能會(huì)不太習(xí)慣,我個(gè)人很習(xí)慣這樣的處理方式。這塊我們也遇到一些問(wèn)題,踩過(guò)一些坑,這個(gè)在***會(huì)跟大家分享。

剛剛是團(tuán)隊(duì)需求、技術(shù)需求方面。接下來(lái)我們更關(guān)注業(yè)務(wù)需求方面。我們剛才提到三點(diǎn):

***,安全性。從安全性角度出發(fā)為什么選擇 Golang?選擇 Golang 靠不靠譜?一個(gè)支付系統(tǒng),它的整個(gè)處理流程的安全性,實(shí)際上涉及到方方面面,包括數(shù)據(jù)傳輸?shù)陌踩?,是否有?shù)據(jù)泄露的風(fēng)險(xiǎn),是否有防篡改的措施;數(shù)據(jù)落地存儲(chǔ)的時(shí)候,存儲(chǔ)是不是關(guān)鍵信息有做加密;網(wǎng)絡(luò)方面,網(wǎng)絡(luò)是不是有接入層、防火墻等等。整個(gè)系統(tǒng)的安全性,從接入層到應(yīng)用層、系統(tǒng)組件,再到 Database,每一層可能都會(huì)有相應(yīng)安全性方面的考量。落地到編程語(yǔ)言選擇,Golang 的安全性靠不靠譜呢?編程語(yǔ)言的安全性更關(guān)注什么呢?很自然的想到一點(diǎn)就是語(yǔ)言的漏洞。

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 2

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

第二,穩(wěn)定性。其實(shí)和安全性類似的一點(diǎn)是,同樣需要考量在系統(tǒng)整體架構(gòu),系統(tǒng)各個(gè)層級(jí)等方面的穩(wěn)定性。昨天下午 B 站的老師也跟大家分享了微服務(wù)演進(jìn)過(guò)程中,系統(tǒng)穩(wěn)定性方面的考量,限流、容錯(cuò)、故障隔離等。系統(tǒng)的接入層限流是不是足夠好,應(yīng)用層是不是高可用,緩存、數(shù)據(jù)庫(kù)等組件也都需要有穩(wěn)定性方面相應(yīng)的考量。同樣,落地到我們的編程語(yǔ)言應(yīng)用實(shí)現(xiàn)方面,在穩(wěn)定性上更關(guān)注的是什么內(nèi)容呢?在我們看來(lái),應(yīng)用高可用架構(gòu),即應(yīng)用的實(shí)現(xiàn)要做到無(wú)狀態(tài),支持橫向擴(kuò)展。其實(shí)這一點(diǎn),不管是 Golang 還是 Java 還是其他的語(yǔ)言,只要結(jié)構(gòu)、代碼設(shè)計(jì)的好, 做到這一點(diǎn) 沒(méi)有什么壓力。

第三,吞吐量。隨著業(yè)務(wù)發(fā)展,交易量逐步增加,客戶越來(lái)越多,吞吐量是否得到很好的支撐?在這方面,準(zhǔn)備了兩個(gè)并發(fā)處理能力方面的例子。這兩個(gè)也是我們系統(tǒng)中會(huì)經(jīng)常用到的功能。一個(gè)是 http 接口的并發(fā)處理能力, 另外一個(gè)是 RSA 加解密的例子。

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 3

如圖 3 所示是我的實(shí)驗(yàn)環(huán)境,是用自己的 MacBook,雙核 8G 的環(huán)境,Golang 是 1.7 的版本。同時(shí)為了有一個(gè)對(duì)標(biāo)的效果,單獨(dú)拿 Golang 看它的效率可能看不出什么,因此拿 Java 做了一個(gè)對(duì)標(biāo),再?gòu)?qiáng)調(diào)一遍, 只是一個(gè)對(duì)標(biāo)的目的, 沒(méi)有黑 Java 的意思。

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 4

如圖 4 所示,我們來(lái)看***個(gè)http 接口,這是 Golang 版本非常簡(jiǎn)單的 http 接口,這個(gè)不用多說(shuō),大家看一眼也知道,十幾行的代碼,啟動(dòng)一個(gè) http 服務(wù),收到一個(gè)請(qǐng)求以后,應(yīng)答,回十個(gè)字節(jié),這是 Golang 的版本。Java 版本做的事情是一樣,但是 Java 代碼比較多,沒(méi)有截全,因?yàn)? Java 的 http 本身沒(méi)有帶多線程的方式,寫了一個(gè)簡(jiǎn)單的線程池,用多線程的方式去處理 http 的請(qǐng)求。

接下來(lái)是測(cè)試的結(jié)果,十個(gè)用戶一萬(wàn)個(gè)請(qǐng)求進(jìn)行測(cè)試。上面是一個(gè) Golang 的結(jié)果,吞吐量 12000 多,請(qǐng)求 響應(yīng) 時(shí)間是 0.815 毫秒。下面是 Java 版本,吞吐量是 11000 多,響應(yīng)時(shí)間是0.891 毫秒,這兩個(gè)版本差別不大,非常相近。從 http 接口方面來(lái)說(shuō),Java 和 Golang 的處理結(jié)果相差不是很大。

下一個(gè)例子是 RSA 加解密處理。上面是 Golang 的版本,也是采用并發(fā)處理的方式,循環(huán) 1000 次,每次進(jìn)行一次加密、一次解密,加密的密鑰用 2048 byte 長(zhǎng) 度的密鑰,待加密的數(shù)據(jù)是 245 byte。下面是 Java 的版本,也是截了一部分出來(lái),實(shí)現(xiàn)方式和 Golang 實(shí)現(xiàn)方式一樣。

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 5

我們直接看結(jié)果,如圖 5 所示,上面是 Golang 的結(jié)果,下面是 Java 的結(jié)果, 用 的是 Mac 自帶的 time 命令來(lái)統(tǒng)計(jì)耗時(shí)。Golang 的結(jié)果,程序?qū)嶋H執(zhí)行時(shí)間(real time)是 2.78 秒 ,J ava 執(zhí)行時(shí)間是 7.74 秒,這里會(huì)看到三倍左右的差距。這個(gè)只能說(shuō)明在 RSA 加解密處理的簡(jiǎn)單場(chǎng)景上面,使用各自的標(biāo)準(zhǔn)庫(kù),可能 Golang 的效率會(huì)比 Java 實(shí)現(xiàn) 效率 更高一些。當(dāng)然大家也可以很容易的找出一些反例,在某些場(chǎng)景,Java 比 Golang 的實(shí)現(xiàn)效率更高一些。什么意思呢?從不同的場(chǎng)景,不同語(yǔ)言的實(shí)現(xiàn)效率或者好一些或者壞一些。對(duì)于我們選擇 Golang 來(lái)說(shuō),只要我們證明它在 我們常用的一些場(chǎng)景 效率沒(méi)有問(wèn)題,我們就可以用 Golang 來(lái)做這套系統(tǒng) 。

實(shí)際上我們對(duì)于 Golang 的吞吐量方面的信心,一方面源于我們的測(cè)試結(jié)果,另一方面其實(shí)在我們搭建這套掃碼支付系統(tǒng)之前,我們還使用 Golang 做過(guò)另一個(gè)秒殺系統(tǒng)。這個(gè)秒殺系統(tǒng)***個(gè)版本是使用 Java 來(lái)做擋板服務(wù)器,但是,可能是我們參數(shù)調(diào)優(yōu)沒(méi)有做好,在壓力測(cè)試的時(shí)候,單臺(tái)壓到 500 tps 就上不去了。但由于時(shí)間緊任務(wù)重,沒(méi)有來(lái)得及做仔細(xì)的參數(shù)調(diào)優(yōu),我們換成用 Golang 試了試。結(jié)果一晚上的開(kāi)發(fā)時(shí)間,輕松幾萬(wàn)上去沒(méi)有什么問(wèn)題。這也使得我們?cè)? Golang 吞吐量方面建立了很強(qiáng)的信心。

從業(yè)務(wù)需求角度考慮,不管是安全性、穩(wěn)定性、吞吐量,選擇 Golang 都沒(méi)有什么壓力。

***總結(jié)一下,我們最終選擇 Golang 的出發(fā)點(diǎn):作為需要快速原型、快速迭代的項(xiàng)目,需要的開(kāi)發(fā)效率非常高,在滿足當(dāng)前和未來(lái)可預(yù)期的高可用、吞吐量等業(yè)務(wù)需求的前提下, Golang 的高效開(kāi)發(fā)效率,簡(jiǎn)單部署和運(yùn)維,是我們擁抱 Golang 的主要原因。

以上是整個(gè)技術(shù)選型方面的考量 關(guān)鍵點(diǎn), 多說(shuō)一句,剛才多次提到系統(tǒng)的吞吐量、高可用的關(guān)鍵點(diǎn),其實(shí)除了編程語(yǔ)言這一層,更多的可能跟整體的系統(tǒng)架構(gòu)有很大關(guān)系,當(dāng)然這是另一個(gè)話題了。

架構(gòu)演進(jìn)

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 6

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

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 7

如圖 7 所示的架構(gòu)是我們幾個(gè)月之前的系統(tǒng)結(jié)構(gòu),比***個(gè)版本復(fù)雜很多。主要的掃碼處理系統(tǒng)是在圖左。我們看應(yīng)用層,從一個(gè)單體應(yīng)用延伸出了多個(gè),包括我們剛剛提到的不同類型的服務(wù):掃碼網(wǎng)關(guān)的實(shí)時(shí)交易處理服務(wù),為商戶提供對(duì)賬報(bào)表的 批處理的服務(wù) ,為商戶提供信息查詢的 平臺(tái)服務(wù)。 另外還搭建了我們的風(fēng)控系統(tǒng),因?yàn)轱L(fēng)控在整個(gè)支付交易處理中也是非常重要的方面。APP 后臺(tái),是我們 iOS、安卓的 App 提供的單獨(dú)的后臺(tái)服務(wù)。整個(gè)這一套系統(tǒng),都是 使用 Golang 實(shí)現(xiàn)的。Golang 在統(tǒng)一系統(tǒng)實(shí)現(xiàn)的技術(shù)棧方面,為我們提供了很大的幫助 。 中間件方面 ,為了 解耦和提高穩(wěn)定性, 我們引入了kafka、redis等系統(tǒng)組件。 為了實(shí)現(xiàn)跨機(jī)房災(zāi)備系統(tǒng)搭建,我們自研了一套數(shù)據(jù)庫(kù)的同步工具,可以從 MongoDB 文檔型的數(shù)據(jù)庫(kù),將數(shù)據(jù)實(shí)時(shí)同步到 MongoDB 或者 MySQL 等其他關(guān)系型數(shù)據(jù)庫(kù),這套工具也是使用 Golang 來(lái)做的。

在整個(gè)架構(gòu)的完善方面,根據(jù)業(yè)務(wù)職能拆出更多的系統(tǒng)。目前我們的系統(tǒng)在此基礎(chǔ)之上,進(jìn)行了更多的一些往服務(wù)化方面的逐步演進(jìn),這是整個(gè)系統(tǒng)架構(gòu)演進(jìn)的過(guò)程。

一些坑

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 8

如圖 8 所示,很簡(jiǎn)單的 十幾行代碼,它提供的是 TCP 長(zhǎng)連接服務(wù)端的服務(wù)。每 accept 一條鏈接,收到客戶端的請(qǐng)求之后,開(kāi)一個(gè) goroutine,通過(guò) handleConnection 這個(gè)函數(shù)進(jìn)行客戶端連接的處理。針對(duì) handleConnection 這個(gè)函數(shù)進(jìn)行了一層包裝,稱之為 TcpRecoverWrap,包裝里做了什么,看名字也知道,是一個(gè) recover 的包裝,具體的實(shí)現(xiàn)在圖右,非常簡(jiǎn)單,也是 Golang 里面比較常用的處理方式,給一個(gè)函數(shù)加一個(gè)包裝,包裝里面加一個(gè) defer 進(jìn)行 recover 處理。

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 9

這段代碼看起來(lái)很簡(jiǎn)單,那么問(wèn)題來(lái) 了 ,是不是在 handleConnection 函數(shù)內(nèi)發(fā)生的任何 panic 都能通過(guò) TcpRecoverWrap 這樣的實(shí)現(xiàn)方式來(lái)解決?既然提出這個(gè)問(wèn)題,答案肯定是否定的。來(lái)看一下 handleConnection 的具體 實(shí)現(xiàn),如圖 9 右邊所示,是一個(gè) TCP 的服務(wù)端,已經(jīng) accept 一個(gè)鏈接,開(kāi)始 read,在一個(gè)死循環(huán)里面進(jìn)行 read 操作,每 read 一條客戶端發(fā)來(lái)的請(qǐng)求信息,開(kāi)一個(gè) goroutine 進(jìn)行實(shí)際的業(yè)務(wù)處理,把讀到的消息給到業(yè)務(wù)處理的函數(shù),當(dāng)業(yè)務(wù)處理完成,拿到業(yè)務(wù)處理結(jié)果以后,把結(jié)果寫到一個(gè) channel 里面,這個(gè)結(jié)果由另一個(gè) goroutine 來(lái)接收,接收到以后把應(yīng)答的消息回復(fù)給 TCP 客戶端,也是很簡(jiǎn)單的一段代碼。

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

第二個(gè) chan 操作問(wèn)題。我們知道在寫 chan 的時(shí)候,如果 chan 已經(jīng)被關(guān)了,那么對(duì)它進(jìn)行寫入操作會(huì) panic。我們看圖9中的 writeMsgQueue 這個(gè) chan ,在 defer 里面進(jìn)行了關(guān)閉。當(dāng)這個(gè) TCP 連接不可用的時(shí)候, handleConnection 函數(shù) return 之前關(guān)閉這個(gè) chan,目的是 chan 關(guān)閉后,通過(guò)檢查 chan 狀態(tài),可以促使 goroutine 退出,避免 goroutine 泄露,但是這個(gè) defer 的 close 引入了另一個(gè)問(wèn)題,如果服務(wù)端收到消息、開(kāi) goroutine 進(jìn)行業(yè)務(wù)處理的過(guò)程中,客戶端已經(jīng)斷開(kāi)了連接,那么此時(shí) chan 已經(jīng)關(guān)閉了,當(dāng)服務(wù)端業(yè)務(wù)處理完成的時(shí)候,寫入一個(gè)已關(guān)閉的 chan ,就會(huì)panic。更可怕的是,這個(gè) panic 是不能被 TcpRecoverWrap 包裝的,因?yàn)樵趫?zhí)行 defer 結(jié)束、關(guān)閉了chan 之后,handleConnection 函數(shù)就已經(jīng) return,也就是這個(gè) panic 是發(fā)生在另一個(gè) goroutine 的,和 handleConnection 函數(shù)沒(méi)有關(guān)系,很顯然剛才的包裝方式是沒(méi)有辦法捕捉這樣的 panic 進(jìn)行 recover 的。

Go語(yǔ)言在掃碼支付系統(tǒng)中的成功實(shí)踐
圖 10

今天分享的內(nèi)容大概就是這些,那么怎么修這些問(wèn)題呢?很簡(jiǎn)單,變量作用域拿到 for 循環(huán)里面,panic 的問(wèn)題可以加另外一個(gè) tcp 關(guān)閉信號(hào),通過(guò)這樣的方式,來(lái)修復(fù)剛才說(shuō)的兩個(gè)問(wèn)題。當(dāng)然修復(fù)方式可能有很多種,僅供大家參考。

責(zé)任編輯:未麗燕 來(lái)源: 推酷
相關(guān)推薦

2019-01-15 09:10:17

邊緣計(jì)算數(shù)據(jù)中心IT

2019-01-16 10:33:41

Linux

2010-06-25 19:07:38

SAP

2014-09-01 09:57:11

Go產(chǎn)品環(huán)境最佳語(yǔ)言

2020-04-20 11:09:30

DevOps實(shí)踐因素

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語(yǔ)言

2022-04-18 09:41:14

Go架構(gòu)設(shè)計(jì)

2023-10-11 07:20:17

2021-11-30 07:31:42

微信支付寶付款

2023-12-13 07:19:01

微服務(wù)架構(gòu)Golang

2011-09-30 13:54:10

H3C云網(wǎng)絡(luò)云安全

2018-04-08 15:33:37

移動(dòng)支付支會(huì)寶微信

2021-04-26 22:17:48

計(jì)算

2021-10-19 09:46:22

ReactGo 技術(shù)

2019-05-21 15:15:22

掃碼乘車公交卡支付方式

2017-12-18 18:23:09

支付寶掃碼賺錢支付寶套路
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)