最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

011、案例實戰(zhàn):每日百萬交易的支付系統(tǒng),如何設(shè)置JVM堆內(nèi)存大???

2023-06-01 21:37 作者:儒猿課堂  | 我要投稿

案例實戰(zhàn)

每日百萬交易的支付系統(tǒng),如何設(shè)置JVM堆內(nèi)存大???


目錄:

  1. 前文回顧

  2. 支付系統(tǒng)背景引入

  3. 支付的核心業(yè)務(wù)流程

  4. 每日百萬交易的支付系統(tǒng)的壓力在哪里?

  5. 支付系統(tǒng)每秒鐘需要處理多少筆支付訂單?

  6. 每個支付訂單處理要耗時多久?

  7. 每個支付訂單大概需要多大的內(nèi)存空間?

  8. 每秒發(fā)起的支付請求對內(nèi)存的占用

  9. 讓支付系統(tǒng)運行起來分析一下

  10. 對完整的支付系統(tǒng)內(nèi)存占用需要進(jìn)行預(yù)估

  11. 支付系統(tǒng)的JVM堆內(nèi)存應(yīng)該怎么設(shè)置?

  12. 本文總結(jié)

  13. 昨日思考題解答

  14. 今日思考題


1、前文回顧

本文是我們專欄的第一個案例,我將用一個每日百萬交易的支付系統(tǒng)作為背景,來給大家分析一下,咱們在上線部署一個系統(tǒng)時,應(yīng)該如何根據(jù)系統(tǒng)的業(yè)務(wù)量來合理的設(shè)置JVM的堆內(nèi)存大小。

通過之前的文章,大家其實都知道我們寫好的代碼在JVM中運行的基本原理了,而且也知道通過什么參數(shù)可以設(shè)置JVM各個內(nèi)存區(qū)域的大小。

但單看之前的文章,大家在自己部署一個線上系統(tǒng)的時候,一定還是會兩眼一蒙圈,發(fā)現(xiàn)自己壓根兒就不知道怎么來設(shè)置自己線上系統(tǒng)的JVM內(nèi)存大小

所以我們通過一個案例來分析一下,教會大家自己負(fù)責(zé)的線上系統(tǒng),到底該如何合理設(shè)置JVM內(nèi)存大小。


2、支付系統(tǒng)背景引入

先來看看,如果在一個電商系統(tǒng)里,一個支付系統(tǒng)大概應(yīng)該是一個什么樣的位置,如下圖。

其實只要大家網(wǎng)購過,大概的流程都會非常的清晰,假設(shè)我們在一個APP或者一個網(wǎng)站里買東西,大體上都是對一些商品加到購物車?yán)铮缓笙聜€訂單,接著對訂單進(jìn)行支付,錢從我們的賬戶劃撥到人家網(wǎng)站的賬戶里去,大致如此。

上面的圖就很清晰的展示了這個過程,所謂的支付系統(tǒng),是一個網(wǎng)站或者APP后臺系統(tǒng)中非常核心的一個環(huán)節(jié),負(fù)責(zé)管理公司的資金流

它負(fù)責(zé)對接用戶的支付請求,然后根據(jù)用戶的付款方式,跟第三方的支付渠道對接起來,比如微信、支付寶,等等。

比如用戶通過微信付款88元,那么他的錢在微信錢包里,需要劃撥88塊到電商公司賬戶里去,那么此時支付系統(tǒng)就得跟微信支付渠道對接,資金從微信劃撥過來,大概的流程就是這個意思。


3、支付的核心業(yè)務(wù)流程

接著我們來講一下支付的核心業(yè)務(wù)流程,大家先看下面的圖。

通過上圖標(biāo)號序號的步驟,大家可以很清晰的知道這個流程了

首先用戶在我們的商城系統(tǒng)提交支付一個訂單的請求,接著商城系統(tǒng)把這個請求提交給支付系統(tǒng),支付系統(tǒng)就會生成一個支付訂單,此時訂單狀態(tài)可能是“待支付”的狀態(tài)。

然后支付系統(tǒng)指引用戶跳轉(zhuǎn)到付款頁面,選擇一個付款方式

然后用戶發(fā)起實際支付請求,支付系統(tǒng)把實際支付請求轉(zhuǎn)交給第三方支付渠道,比如微信或者支付寶,它們會去處理支付請求進(jìn)行資金轉(zhuǎn)移。

如果微信或者支付寶處理完支付之后,就會返回支付結(jié)果給支付系統(tǒng),支付系統(tǒng)可以更新自己本地的支付訂單的狀態(tài)變成“已完成”。

當(dāng)然,其實一個完整的支付系統(tǒng)還包含很多東西。

比如還要負(fù)責(zé)對賬以及跟合作商戶之間的資金清算,支付系統(tǒng)得包含應(yīng)用管理、賬戶管理、渠道管理、支付交易、對賬管理、清算管理、結(jié)算管理,等各種功能模塊,但是我們這里就關(guān)注最核心的支付流程即可。


4、每日百萬交易的支付系統(tǒng)的壓力在哪里?

接著我們來考慮一下,一個每日百萬交易的支付系統(tǒng)的壓力到底集中在哪里呢?

比如上面的那個核心支付流程,我們的這套系統(tǒng)每日要發(fā)生百萬次交易。

一般達(dá)到百萬交易,要不然是國內(nèi)最大的互聯(lián)網(wǎng)公司,要不就是一個通用型第三方支付平臺,對接各種APP的支付交易。

其實大家通過上圖都能明顯看到,上述業(yè)務(wù)流程中,最核心的環(huán)節(jié),就是在用戶發(fā)起支付請求的時候,會生成一個支付訂單

這個支付訂單需要記錄清楚比如是誰發(fā)起支付?對哪個商品的支付?通過哪個渠道進(jìn)行支付?還有發(fā)起支付的時間?等等,諸如此類的信息。

如果每日百萬交易,那么大家可以想象一下,在我們的JVM的角度來看,就是每天會在JVM中創(chuàng)建上百萬個支付訂單對象

大家仔細(xì)想想,是不是這么回事?如下圖:

所以我們的支付系統(tǒng),其實他的壓力有很多方面,包括高并發(fā)訪問、高性能處理請求、大量的支付訂單數(shù)據(jù)需要存儲,等等技術(shù)難點。

但是拋開這些系統(tǒng)架構(gòu)層面的東西,單單是在JVM層面,我們的支付系統(tǒng)最大的壓力,就是每天JVM內(nèi)存里會頻繁的創(chuàng)建和銷毀100萬個支付訂單,所以這里就牽扯到一個核心的問題。

  • 我們的支付系統(tǒng)需要部署多少臺機(jī)器?

  • 每臺機(jī)器需要多大的內(nèi)存空間?

  • 每臺機(jī)器上啟動的JVM需要分配多大的堆內(nèi)存空間?

  • 給JVM多大的內(nèi)存空間才能保證可以支撐這么多的支付訂單在內(nèi)存里的創(chuàng)建,而不會導(dǎo)致內(nèi)存不夠直接崩潰?

這就是我們本文要考慮的核心問題。


5、支付系統(tǒng)每秒鐘需要處理多少筆支付訂單

要解決線上系統(tǒng)最核心的一個參數(shù),也就是JVM堆內(nèi)存大小的合理設(shè)置,我們首先第一個要計算的,就是每秒鐘我們的系統(tǒng)要處理多少筆支付訂單。

假設(shè)每天100萬個支付訂單,那么一般用戶交易行為都會發(fā)生在每天的高峰期,比如中午或者晚上。

假設(shè)每天高峰期大概是幾個小時,用100萬平均分配到幾個小時里,那么大概是每秒100筆訂單左右,咱們就以每秒100筆訂單來計算一下好了。

假設(shè)我們的支付系統(tǒng)部署了3臺機(jī)器,每臺機(jī)器實際上每秒大概處理30筆訂單。

大家看下面的圖,這個圖可以反映出來支付系統(tǒng)每秒鐘的訂單處理壓力。


6、每個支付訂單處理要耗時多久?

下一個問題,咱們必須要搞明白的一個事兒,就是每個支付訂單大概要處理多長時間?

如果用戶發(fā)起一次支付請求,那么支付需要在JVM中創(chuàng)建一個支付訂單對象,填充進(jìn)去數(shù)據(jù),然后把這個支付訂單寫入數(shù)據(jù)庫,還可能會處理一些其他的事情

咱們就假設(shè)一次支付請求的處理,包含一個支付訂單的創(chuàng)建,大概需要1秒鐘的時間。

那么大體上你的腦子里可以出現(xiàn)的一個流動的模型,應(yīng)該是每臺機(jī)器一秒鐘接收到30筆支付訂單的請求,然后在JVM的新生代里創(chuàng)建了30個支付訂單的對象,做了寫入數(shù)據(jù)庫等處理

接著1秒之后,這30個支付訂單就處理完畢,然后對這些支付訂單對象的引用就回收了,這些訂單在JVM的新生代里就是沒人引用的垃圾對象了。

接著再是下一秒來30個支付訂單,重復(fù)這個步驟。


7、每個支付訂單大概需要多大的內(nèi)存空間?

接著我們來計算一下,每個支付訂單對象大概需要多大的內(nèi)存空間?

之前的文章里有一個思考題, 已經(jīng)教過大家這個怎么計算了,其實不考慮別的,你就直接根據(jù)支付訂單類中的實例變量的類型來計算就可以了。

比如說支付訂單類如下所示,你只要記住一個Integer類型的變量數(shù)據(jù)是4個字節(jié),Long類型的變量數(shù)據(jù)是8個字節(jié),還有別的類型的變量數(shù)據(jù)占據(jù)多少字節(jié)

百度一下都可以查到,然后就可以計算出每個支付訂單對象大致占據(jù)多少字節(jié)。

一般來說,比如支付訂單這種核心類,你就按20個實例變量來計算,然后一般大概一個對象也就在幾百字節(jié)的樣子

我們算他大一點好了,就算一個支付訂單對象占據(jù)500字節(jié)的內(nèi)存空間,不到1kb。


8、每秒發(fā)起的支付請求對內(nèi)存的占用

之前說過,假設(shè)有3臺機(jī)器,每秒鐘處理30筆支付訂單的請求,那么在這1秒內(nèi),大家都知道,肯定是有方法里的局部變量在引用這些支付訂單的,如下圖:

那么30個支付訂單,大概占據(jù)的內(nèi)存空間是30 * 500字節(jié) = 15000字節(jié),大概其實也就15kb而已。其實是非常非常小的。


9、讓支付系統(tǒng)運行起來分析一下

現(xiàn)在我們已經(jīng)把整個系統(tǒng)運行的關(guān)鍵環(huán)節(jié)的數(shù)據(jù)都分析清楚了,大家可以大致腦子里思考一下,每秒30個支付請求,創(chuàng)建30個支付訂單對象,也就占據(jù)kb級別的內(nèi)存空間而已

然后接著1秒過后,這30個對象就沒有人引用了,就成了新生代里的垃圾了。

下一秒請求過來,我們的系統(tǒng)持續(xù)的創(chuàng)建支付訂單對象,不停在新生代里放入30個支付訂單,然后新生代里的對象會持續(xù)的累積和增加。

直到有一刻,發(fā)現(xiàn)可能新生代里都有幾十萬個對象了,此時占據(jù)了幾百MB的空間了,可能新生代空間就快滿了。

然后就會觸發(fā)Minor GC,就把新生代里的垃圾對象都給回收掉了,騰出內(nèi)存空間,然后繼續(xù)來在內(nèi)存里分配新的對象。

這就是這個業(yè)務(wù)系統(tǒng)的運行模型。


10、對完整的支付系統(tǒng)內(nèi)存占用需要進(jìn)行預(yù)估

之前的分析,全部都是基于一個核心業(yè)務(wù)流程中的一個支付訂單對象來分析的,其實那只是一小部分而已。

真實的支付系統(tǒng)線上運行,肯定每秒會創(chuàng)建大量其他的對象,但是我們結(jié)合這個訪問壓力以及核心對象的內(nèi)存占據(jù),大致可以來估算一下整個支付系統(tǒng)每秒鐘大致會占據(jù)多少內(nèi)存空間。

其實如果你要估算的話,可以把之前的計算結(jié)果擴(kuò)大10倍~20倍。也就是說,每秒鐘除了在內(nèi)存里創(chuàng)建支付訂單對象,還會創(chuàng)建其他數(shù)十種對象。

那么每秒鐘創(chuàng)建出來的被棧內(nèi)存的局部變量引用的對象大致占據(jù)的內(nèi)存空間就在幾百KB~1MB之間。

然后下一秒繼續(xù)來新的請求創(chuàng)建大概1MB的對象放在新生代里,接著變成垃圾,再來下一秒。

循環(huán)多次之后,新生代里垃圾太多,就會觸發(fā)Minor GC回收掉這些垃圾。這就是一個完整系統(tǒng)的大致JVM層面的內(nèi)存使用模型。


11、支付系統(tǒng)的JVM堆內(nèi)存應(yīng)該怎么設(shè)置?

其實結(jié)合支付系統(tǒng)的核心業(yè)務(wù)流程分析清楚了之后,大家就完全知道這么一個線上系統(tǒng),每個機(jī)器上部署上線的時候,JVM的堆內(nèi)存應(yīng)該如何設(shè)置了。

其實一般來說這種線上業(yè)務(wù)系統(tǒng),常見的機(jī)器配置是2核4G,或者是4核8G。

如果我們用2核4G的機(jī)器來部署,那么還是有點緊湊的,因為機(jī)器有4G內(nèi)存,但是機(jī)器本身也要用一些內(nèi)存空間,最后你的JVM進(jìn)程最多就是2G內(nèi)存

然后這2G還得分配給方法區(qū)、棧內(nèi)存、堆內(nèi)存幾塊區(qū)域,那么堆內(nèi)存可能最多就是個1G多的內(nèi)存空間。

然后堆內(nèi)存還分為新生代和老年代,你的老年代總需要放置系統(tǒng)的一些長期存活的對象吧,怎么也得給幾百MB的內(nèi)存空間,那么新生代可能也就幾百MB的內(nèi)存了。

這樣的話,大家可以看到,我們上述的核心業(yè)務(wù)流程,只不過僅僅是針對一個支付訂單對象來分析的,但是實際上如果擴(kuò)大10倍~20倍換成對完整系統(tǒng)的預(yù)估之后,我們看到,大致每秒會占據(jù)1MB左右的內(nèi)存空間。

那么如果你新生代就幾百MB的內(nèi)存空間,是不是會導(dǎo)致運行幾百秒之后,新生代內(nèi)存空間就滿了?此時是不是就得觸發(fā)Minor GC了?

其實如果這么頻繁的觸發(fā)Minor GC,會影響線上系統(tǒng)的性能穩(wěn)定性,具體原因后續(xù)再說。

這里大家首先要明白的一點,就是頻繁觸發(fā)GC一定不是什么好事兒。

因此你可以考慮采用4核8G的機(jī)器來部署支付系統(tǒng),那么你的JVM進(jìn)程至少可以給4G以上內(nèi)存,新生代在里面至少可以分配到2G內(nèi)存空間

這樣子就可以做到可能新生代每秒多1MB左右的內(nèi)存,但是需要將近半小時到1小時才會讓新生代觸發(fā)Minor GC,這就大大降低了GC的頻率。

舉個例子:機(jī)器采用4核8G,然后-Xms和-Xmx設(shè)置為3G,給整個堆內(nèi)存3G內(nèi)存空間,-Xmn設(shè)置為2G,給新生代2G內(nèi)存空間。

而且假設(shè)你的業(yè)務(wù)量如果更大,你可以考慮不只部署3臺機(jī)器,可以橫向擴(kuò)展部署5臺機(jī)器,或者10臺機(jī)器,這樣每臺機(jī)器處理的請求更少,對JVM的壓力更小。


12、本文總結(jié)

本文從一個支付系統(tǒng)案例出發(fā),帶著大家一點點計算了這個系統(tǒng)在日百萬交易的壓力下,部署3臺機(jī)器的場景下,每秒鐘每臺機(jī)器需要處理多少筆訂單,每筆訂單要耗時多久處理,每秒鐘會對JVM占據(jù)多大內(nèi)存空間,根據(jù)這個橫向擴(kuò)展預(yù)估整個系統(tǒng)每秒需要占據(jù)多大內(nèi)存空間。

接著根據(jù)上述數(shù)據(jù)模型推算出,在不同的機(jī)器配置之下,你的新生代大致會有多大的內(nèi)存空間,然后在不同的新生代大小之下,多久會觸發(fā)一次Minor GC

為了避免頻繁的GC,那么應(yīng)該選用什么樣的機(jī)器配置,部署多少臺機(jī)器,給JVM堆內(nèi)存多大的內(nèi)存空間,新生代多大的內(nèi)存空間。

根據(jù)這套配置,就可以推算出來整個系統(tǒng)的運行模型了,每秒鐘創(chuàng)建多少對象在新生代,然后1秒之后成為垃圾,大概系統(tǒng)運行多久,新生代會觸發(fā)一次GC,頻率有多高 。


13、昨日思考題解答

昨天讓大家思考Spring Boot和Tomcat部署系統(tǒng)怎么設(shè)置JVM參數(shù)

很多同學(xué)都找到了,Spring Boot其實就是啟動的時候可以加上JVM參數(shù),Tomcat就是在bin目錄下的catalina.sh中可以加入JVM參數(shù)

這個題目不難,主要是讓大家建立起來一個意識,就是你得關(guān)注你部署的系統(tǒng)的JVM參數(shù)是怎么來設(shè)置的。


14、今日思考題

今天開始案例分析環(huán)節(jié)了,那思考題很簡單,大家當(dāng)然是應(yīng)該去思考一下自己平時開發(fā)的系統(tǒng):

  • 你會去按照本文類似的思路估算系統(tǒng)壓力嗎?

  • 你會去估算系統(tǒng)的JVM內(nèi)存壓力嗎?

  • 然后會去有針對性的合理設(shè)置JVM參數(shù)嗎?

  • 你們之前是這么做的嗎?為什么?


上述幾個問題,就是今天的思考題。

End


版權(quán):公眾號儒猿技術(shù)窩

未經(jīng)許可不得傳播,如有侵權(quán)將追究法律責(zé)任

太仆寺旗| 文昌市| 南江县| 海林市| 乐业县| 罗城| 龙岩市| 株洲县| 建瓯市| 苍山县| 阿拉善左旗| 黄梅县| 讷河市| 常德市| 鄱阳县| 休宁县| 玉环县| 长春市| 文安县| 高雄市| 萨嘎县| 淮北市| 康平县| 塘沽区| 黄龙县| 固镇县| 亳州市| 武清区| 武定县| 乌拉特后旗| 景谷| 乐清市| 特克斯县| 平阳县| 额济纳旗| 西乌珠穆沁旗| 泸溪县| 眉山市| 高雄市| 奉节县| 寿光市|