洪亮
摘要:商用App因?yàn)槭褂萌藬?shù)較多,對(duì)于服務(wù)端數(shù)據(jù)庫(kù)訪問(wèn)有著較高的要求。如果數(shù)據(jù)訪問(wèn)架構(gòu)不合理,當(dāng)訪問(wèn)請(qǐng)求較多時(shí),容易出現(xiàn)訪問(wèn)超時(shí)的情況。文中,主要就對(duì)商用App服務(wù)端數(shù)據(jù)訪問(wèn)架構(gòu)改造進(jìn)行了分析。
關(guān)鍵詞:商用App;服務(wù)端;數(shù)據(jù)訪問(wèn);架構(gòu)
中圖分類號(hào):TP393 文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1009-3044(2020)21-0076-02
開放科學(xué)(資源服務(wù))標(biāo)識(shí)碼(0SID):
1 背景研究
1.1系統(tǒng)商用問(wèn)題
某國(guó)某運(yùn)營(yíng)商的掌上App項(xiàng)目中,近期出現(xiàn)了用戶使用過(guò)程中App響應(yīng)慢,卡頓甚至系統(tǒng)崩潰的問(wèn)題。經(jīng)過(guò)問(wèn)題排查發(fā)現(xiàn)問(wèn)題大概率出現(xiàn)在業(yè)務(wù)高峰期,并且隨著用戶量的增加,問(wèn)題的出現(xiàn)概率越高。系統(tǒng)前端向服務(wù)端的請(qǐng)求出現(xiàn)超時(shí)。進(jìn)而檢查服務(wù)端,發(fā)現(xiàn)超時(shí)的原因在于數(shù)據(jù)庫(kù)鏈接滿載,讀寫吞吐量達(dá)到瓶頸導(dǎo)致請(qǐng)求超時(shí)。
1.2系統(tǒng)服務(wù)端架構(gòu)分析
通過(guò)對(duì)目前系統(tǒng)服務(wù)端的架構(gòu)做分析,發(fā)現(xiàn)目前服務(wù)端是采用的單一數(shù)據(jù)訪問(wèn)架構(gòu),服務(wù)端通過(guò)web項(xiàng)目將業(yè)務(wù)服務(wù)封裝為restful接口給前端App調(diào)用,服務(wù)端的業(yè)務(wù)類訪問(wèn)單一的Mysql數(shù)據(jù)庫(kù),當(dāng)讀寫數(shù)據(jù)量大時(shí),業(yè)務(wù)類到Mysql的鏈接處就出現(xiàn)了瓶頸,出現(xiàn)了上面提到的問(wèn)題。所以為了解決這個(gè)問(wèn)題就必須改造現(xiàn)網(wǎng)系統(tǒng)服務(wù)端的數(shù)據(jù)訪問(wèn)架構(gòu),從單一數(shù)據(jù)庫(kù)訪問(wèn)改造為分布式或集群架構(gòu),用來(lái)擴(kuò)展數(shù)據(jù)庫(kù)訪問(wèn)效率和吞吐量,并可提升數(shù)據(jù)訪問(wèn)的高可用性。
1.3 架構(gòu)選型
目前業(yè)界有多種Mysql數(shù)據(jù)庫(kù)的分布式/集群方案,通過(guò)對(duì)各種方案的優(yōu)劣并結(jié)合項(xiàng)目實(shí)際情況為本次的改造選擇使用MysqI+Mycat的架構(gòu),中間件對(duì)代碼影響最小,易于架構(gòu)改動(dòng),以及后期擴(kuò)展。
2 架構(gòu)實(shí)現(xiàn)
第一部分的改造將一臺(tái)Mysql數(shù)據(jù)庫(kù)擴(kuò)展為兩臺(tái)Mysql,一主一備,通過(guò)原生的復(fù)制機(jī)制實(shí)現(xiàn)雙向復(fù)制,加入Mycat中間件代理兩臺(tái)Mysql,實(shí)現(xiàn)讀寫的負(fù)載均衡,并且Mycat通過(guò)心跳機(jī)制檢測(cè)到主庫(kù)宕機(jī)后,自動(dòng)切換到備機(jī)。業(yè)務(wù)測(cè)代碼不需要修改,只需要修改數(shù)據(jù)庫(kù)的連接由Mysql的地址切換到Mycat即可。
第二部分的改造也有兩種方案,第一種:將一臺(tái)Mycat擴(kuò)展為兩臺(tái),業(yè)務(wù)測(cè)訪問(wèn)VIP(虛擬IP),兩臺(tái)keepalive競(jìng)爭(zhēng)VIP,并由HAproxy轉(zhuǎn)發(fā)到其中一臺(tái)Mycat,實(shí)現(xiàn)負(fù)載均衡高可用。
第二種:Mycat依舊為兩臺(tái),但是負(fù)載均衡不在服務(wù)端,而是放在客戶端(及業(yè)務(wù)代碼端),使用java原生提供的LoadBal-ancing協(xié)議,將對(duì)數(shù)據(jù)庫(kù)的讀寫請(qǐng)求負(fù)載在多個(gè)MYcat實(shí)例上實(shí)現(xiàn)Mycat的高可用。LoadBalancing原理:mysql connector/J驅(qū)動(dòng)創(chuàng)建的LoadBalancedConnection是一個(gè)邏輯鏈接,其內(nèi)部持有一個(gè)物理鏈接列表,即與每個(gè)host建立一個(gè)Connection。url中的每個(gè)host都是平等的主host,當(dāng)客戶端獲取連接時(shí)會(huì)有兩種random(默認(rèn)隨機(jī))和bestResponseTime(最小響應(yīng)時(shí)間)兩種均衡策略,可以在參數(shù)** loadBalanceStrategy**中指定,架構(gòu)圖如圖1。
關(guān)于兩種方案的選擇,方案一自定義軟負(fù)載是自己實(shí)現(xiàn)的,功能單一,負(fù)載策略只有輪詢,而且健康檢查在很長(zhǎng)一段時(shí)間出現(xiàn)連接泄露的問(wèn)題,穩(wěn)定性不夠好,還需要做一些優(yōu)化和測(cè)試進(jìn)行打磨;方案二是基于mysql的Java連接驅(qū)動(dòng)做的負(fù)載均衡,是官方提供的方案,穩(wěn)定性和可用性更高,而且我們?cè)诮?jīng)過(guò)很長(zhǎng)一段時(shí)間的壓測(cè)和容錯(cuò)性測(cè)試,發(fā)現(xiàn)其性能很優(yōu)越,負(fù)載均衡策略也更豐富,使用過(guò)程更簡(jiǎn)單,所以決定使用方案二。
3 環(huán)境搭建
3.1 Mycat+Mysql搭建
首先在兩臺(tái)Linux主機(jī)上安裝Mycat,然后再安裝兩臺(tái)Mysql,端口號(hào)分別為3301和3302,安裝方法這里不贅述。接著對(duì)兩臺(tái)Mycat進(jìn)行配置,分別代理兩臺(tái)Mysql數(shù)據(jù)庫(kù),分別對(duì)server.xml.schemas.xml做相應(yīng)的配置,實(shí)現(xiàn)代理一主一從兩個(gè)Mysql數(shù)據(jù)庫(kù),并且從庫(kù)也為主庫(kù)的備用庫(kù),注意schemas.xml中的balance類型設(shè)置為2,所有的主庫(kù)和從庫(kù)都參與讀操作的負(fù)載均衡。
3.2 功能驗(yàn)證
3.2.1 負(fù)載均衡
啟動(dòng)兩臺(tái)Mysql和兩臺(tái)Mycat,從任意一臺(tái)Mysql主機(jī)訪問(wèn)Mycat,指令為:
mysql -h172.16.23.126 -P8066 -uroot -pmycat0001
端口指向其中一臺(tái)My at,用戶名密碼,執(zhí)行多次查詢操作,讀操作負(fù)載均衡日志中展示的結(jié)果,已實(shí)現(xiàn)了在主從庫(kù)中負(fù)載讀的操作。
3.2.2故障遷移
手動(dòng)停掉主庫(kù)模擬數(shù)據(jù)庫(kù)宕機(jī)的情況,mycat自動(dòng)將從庫(kù)切換為主庫(kù),不影響讀寫操作,并且當(dāng)主庫(kù)故障恢復(fù)后,再次測(cè)試多次查詢操作,恢復(fù)到之前的負(fù)載均衡狀態(tài)。
3.2.3 主從復(fù)制
關(guān)于主從復(fù)制功能,因?yàn)槟壳耙恢饕粡牡募軜?gòu)下寫操作都在主庫(kù),讀操作在主庫(kù)與從庫(kù)間負(fù)載,所以需要主從保持復(fù)制同步數(shù)據(jù)。這里使用Mysql原生的復(fù)制機(jī)制,通過(guò)bin log實(shí)現(xiàn)數(shù)據(jù)的同步。驗(yàn)證過(guò)程:同樣登陸mycat,執(zhí)行插入,修改或刪除操作,首先數(shù)據(jù)會(huì)入主庫(kù),查詢主庫(kù)表能夠查詢到寫操作的結(jié)果,這時(shí)再查詢從庫(kù),發(fā)現(xiàn)數(shù)據(jù)和主庫(kù)一致,說(shuō)明復(fù)制操作完成。當(dāng)停掉其中一個(gè)數(shù)據(jù)庫(kù)后,再次執(zhí)行插入,修改或刪除操作,然后手動(dòng)恢復(fù)停掉的數(shù)據(jù)庫(kù),再次查詢?cè)摂?shù)據(jù)庫(kù)的表數(shù)據(jù),發(fā)現(xiàn)兩庫(kù)數(shù)據(jù)保持一致,說(shuō)明在故障恢復(fù)后,主從復(fù)制的機(jī)制仍然有效。
4 性能測(cè)試
4.1 測(cè)試前提準(zhǔn)備
有一個(gè)重要的指標(biāo)需要注意,就是數(shù)據(jù)庫(kù)的最大連接數(shù),要模擬現(xiàn)網(wǎng)項(xiàng)目的真實(shí)場(chǎng)景,這個(gè)配置是至關(guān)重要的,所以首先需要將兩臺(tái)Mysql數(shù)據(jù)庫(kù)的最大連接數(shù)設(shè)置和現(xiàn)網(wǎng)項(xiàng)目保持一致,這里我們?cè)O(shè)置為2000。
4.2 采集樣本準(zhǔn)備
準(zhǔn)備兩組采集樣本,第一組采集對(duì)單例mysql讀操作的性能數(shù)據(jù),初始并發(fā)請(qǐng)求為0,每過(guò)10秒鐘增加100并發(fā)請(qǐng)求,一直增加到并發(fā)5000,然后保持60秒,然后每秒減少100并發(fā),直到并發(fā)為0。通過(guò)對(duì)上述場(chǎng)景下的mysql單例吞吐量,請(qǐng)求書,失敗率三個(gè)方面表現(xiàn)做觀察和分析。第二組則對(duì)Mycat架構(gòu)下一主一從的mysql做讀操作的性能數(shù)據(jù),同樣采用以上的遞增并發(fā)測(cè)試場(chǎng)景。
4.3 壓測(cè)工具準(zhǔn)備
采用開源壓力測(cè)試工具JMeter作為本次的性能壓力測(cè)試工具,并創(chuàng)建壓測(cè)模板。新建兩個(gè)stepping thread group,一個(gè)是連接單例mysql,一個(gè)連接mycat,采用同樣的讀查詢SQL。
4.4 壓測(cè)結(jié)果分析
首先在對(duì)單例mysql的測(cè)試中我們可以看到剛開始時(shí)請(qǐng)求成功的TPS達(dá)到1700左右,然后隨著并發(fā)量的提升,TPS逐漸降低,到4分鐘時(shí)差不多降到1600左右,這個(gè)時(shí)候的并發(fā)請(qǐng)求快到了2000,后面繼續(xù)降低,并且開始出現(xiàn)請(qǐng)求錯(cuò)誤的響應(yīng),繼續(xù)到9分鐘左右,并發(fā)到達(dá)峰值5000,成功請(qǐng)求TPS降到1500左右。
14分鐘總共處理請(qǐng)求數(shù)155萬(wàn),平均響應(yīng)時(shí)長(zhǎng)1014ms,響應(yīng)錯(cuò)誤率13.46%,也就是成功響應(yīng)的請(qǐng)求數(shù)為134萬(wàn)。
然后看mycat代理2臺(tái)mysql負(fù)載均衡的測(cè)試結(jié)果,剛開始時(shí)請(qǐng)求成功的TPS達(dá)到3500左右,然后隨著并發(fā)量的提升,TPS逐漸降低,到4分鐘時(shí)差不多降到3300左右,這個(gè)時(shí)候的并發(fā)請(qǐng)求快到了2000,后面繼續(xù)降低,并且開始出現(xiàn)請(qǐng)求錯(cuò)誤的響應(yīng),繼續(xù)到9分鐘左右,并發(fā)到達(dá)峰值5000,成功請(qǐng)求TPS降到3100左右。
14分鐘總共處理請(qǐng)求數(shù)337萬(wàn),平均響應(yīng)時(shí)長(zhǎng)529ms,響應(yīng)錯(cuò)誤率17.73%,也就是成功響應(yīng)的請(qǐng)求數(shù)為277萬(wàn)。
綜合對(duì)比分析,可見(jiàn)在mycat的代理分布式mysql的環(huán)境下,不論從吞吐量,處理請(qǐng)求書,響應(yīng)延時(shí)以及成功請(qǐng)求數(shù)等各方面,幾乎提升了一倍的性能,效果比較理想。
5 穩(wěn)定性測(cè)試
為了保證在升級(jí)到新的架構(gòu)后數(shù)據(jù)庫(kù)訪問(wèn)的穩(wěn)定性,所以要做穩(wěn)定性測(cè)試,在新的mycat代理2臺(tái)mysql環(huán)境下,繼續(xù)使用JMeter工具壓測(cè),測(cè)試樣本調(diào)整為保持2000并發(fā)請(qǐng)求,并持續(xù)24小時(shí),觀察新架構(gòu)下的數(shù)據(jù)訪問(wèn)穩(wěn)定性,從測(cè)試結(jié)果可以看得出24個(gè)小時(shí)保持高并發(fā)下mycat+mysql表現(xiàn)穩(wěn)定,吞吐量保持在3200-3300左右,平均請(qǐng)求延時(shí)在600ms左右,總共的請(qǐng)求錯(cuò)誤率在1.1%左右,可以說(shuō)結(jié)果比較理想。
6 擴(kuò)展性
目前為止已經(jīng)完成了將單例mysql擴(kuò)展為2臺(tái)mysql負(fù)載均衡的架構(gòu),這里稱為擴(kuò)容階段1。并且通過(guò)壓力測(cè)試結(jié)果可以得出性能確實(shí)提升的結(jié)論,所以再升級(jí)為新的架構(gòu)后,理論上可以有效緩解現(xiàn)網(wǎng)App客戶在使用時(shí)的卡頓、響應(yīng)慢、崩潰等問(wèn)題。當(dāng)然考慮到用戶量的不斷增加,新的架構(gòu)也必須要考慮到良好的擴(kuò)展性,對(duì)于后期的擴(kuò)容本文也給出了響應(yīng)的架構(gòu)演進(jìn),擴(kuò)容階段2將增加兩臺(tái)mysql,一共4臺(tái),做雙主單從,兩主互為主備,相互復(fù)制,主從之前相互復(fù)制,讀操作在4臺(tái)中負(fù)載均衡,效率應(yīng)為階段1的兩倍左右。隨著用戶量繼續(xù)增加,再到擴(kuò)容階段3再增加兩臺(tái)mysql,一共6臺(tái),在雙主的情況下做雙主雙從,這時(shí)可以將負(fù)載均衡策略改為再除了當(dāng)前主機(jī)之外的其他5臺(tái)mysql做讀負(fù)載,主機(jī)只做寫,讀寫分離,讓主機(jī)寫效率更高。如果用戶量還在持續(xù)上升,那么架構(gòu)將演進(jìn)到最終階段,架構(gòu)升級(jí)為N主N從,可以考慮將寫負(fù)載到N臺(tái)主庫(kù)上,所有從庫(kù)做讀負(fù)載均衡。
【通聯(lián)編輯:李雅琪】