神州系統(tǒng)是中通自主研發(fā)的網(wǎng)點(diǎn)智能管理平臺,為網(wǎng)點(diǎn)提供與下屬網(wǎng)點(diǎn)、承包區(qū)、業(yè)務(wù)員、客戶之間的收、派、代收增值等結(jié)算工具,通過系統(tǒng)自動算賬和結(jié)算,網(wǎng)點(diǎn)整體結(jié)算效率提升至2倍以上,降低了財(cái)務(wù)運(yùn)營成本。同時(shí)通過財(cái)務(wù)結(jié)算的自動化,網(wǎng)點(diǎn)收件和到件掃描操作效率約提升50%。
系統(tǒng)還通過大數(shù)據(jù)計(jì)算,將客戶的運(yùn)費(fèi)、件量、發(fā)件區(qū)域占比、重量占比等數(shù)據(jù)報(bào)表快速準(zhǔn)確地展示出來,方便網(wǎng)點(diǎn)分析客戶,提升了網(wǎng)點(diǎn)的市場競爭力。另外,還提供了網(wǎng)點(diǎn)整個(gè)運(yùn)營環(huán)節(jié)的數(shù)據(jù)監(jiān)控,幫助網(wǎng)點(diǎn)糾正錯(cuò)誤操作,減少異常率,提升了網(wǎng)點(diǎn)管理水平,降低了網(wǎng)點(diǎn)的管理成本。
為了保證系統(tǒng)的高可用,實(shí)現(xiàn)海量運(yùn)單數(shù)據(jù)的實(shí)時(shí)賬單運(yùn)算、出賬以及數(shù)據(jù)分析,我們的技術(shù)人員都付出了什么樣的努力,神州系統(tǒng)的架構(gòu)剛開始并不是流行的微服務(wù)架構(gòu),這中間又發(fā)生了什么?下面請大家跟著我一起,探索神州系統(tǒng)的發(fā)展歷程。
神州系統(tǒng)自2017年1月立項(xiàng),根據(jù)當(dāng)時(shí)的情況分析,其中最重要的2個(gè)因素對我們決策有著直接影響。
第一個(gè)因素:數(shù)據(jù)量大,每日賬單數(shù)據(jù)量1600-2000萬不等;
由于MySQL數(shù)據(jù)庫單表記錄數(shù)過多會導(dǎo)致檢索效率下降,數(shù)千萬記錄就會導(dǎo)致普通查詢效率低下,對于聚合函數(shù),更是連千萬級數(shù)據(jù)都無法支撐,而我們的數(shù)據(jù)卻有數(shù)億。為了解決這種問題,我們使用dangdang公司開源框架sharding-jdbc分表分庫的解決方案,以便于我們將單表數(shù)據(jù)量控制在千萬左右。根據(jù)業(yè)務(wù)我們制定了3種分表規(guī)則:按網(wǎng)點(diǎn)、按單號、按時(shí)間。
網(wǎng)點(diǎn)的賬單數(shù)據(jù)理論上不會出現(xiàn)交際,正是借助這一點(diǎn),我們將賬單的數(shù)據(jù)按網(wǎng)點(diǎn)分表,查詢時(shí)針對一個(gè)網(wǎng)點(diǎn)查詢,這樣既能滿足業(yè)務(wù)需要,又能滿足系統(tǒng)性能需要。
而對于熱點(diǎn)數(shù)據(jù),在系統(tǒng)設(shè)計(jì)的過程中,需要多網(wǎng)點(diǎn)共享數(shù)據(jù)時(shí),比如同一個(gè)單號被多個(gè)網(wǎng)點(diǎn)掃描操作,需要將部分?jǐn)?shù)據(jù)共享在多個(gè)網(wǎng)點(diǎn)中,我們則可以采取單號分表,將多個(gè)網(wǎng)點(diǎn)的信息,記錄在一個(gè)單號上。而按時(shí)間周期統(tǒng)計(jì)的數(shù)據(jù)或計(jì)算的中間結(jié)果,則采用按時(shí)間分表。
上面所說的分表規(guī)則都是標(biāo)準(zhǔn)化的規(guī)則,但是標(biāo)準(zhǔn)化的分表規(guī)則,也許并不能完全滿足實(shí)際需要;比如我們就遇到了這樣的問題,按網(wǎng)點(diǎn)分表時(shí),幾十個(gè)網(wǎng)點(diǎn)被分配到1張表中,其中一個(gè)網(wǎng)點(diǎn)業(yè)務(wù)量非常大,數(shù)據(jù)占整張表的97%,使用的時(shí)候,不單當(dāng)前網(wǎng)點(diǎn)無法正常使用,其他網(wǎng)點(diǎn)也受到了牽連。此時(shí)使用特殊分表規(guī)則,將次網(wǎng)點(diǎn)的數(shù)據(jù),單獨(dú)存入一張獨(dú)立的表,此表中只有本網(wǎng)點(diǎn)數(shù)據(jù),根本不需要維護(hù)網(wǎng)點(diǎn)id的索引,可以把更多有效的索引資源放在其他業(yè)務(wù)字段上,大大提高了檢索效率。
另外我們采用了TBSchedule實(shí)現(xiàn)分布式調(diào)度,使海量賬單數(shù)據(jù)由多臺機(jī)器分開運(yùn)算。既保證了海量數(shù)據(jù)計(jì)算的時(shí)效,又保證了服務(wù)器不會重復(fù)運(yùn)算相同的數(shù)據(jù)。同樣我們可以使用自定義的分片規(guī)則,讓多臺服務(wù)器的工作量盡量地保持平衡。
第二個(gè)因素:研發(fā)時(shí)間少,項(xiàng)目要在3個(gè)月內(nèi)上線。
由于時(shí)間的因素,為了能夠快速實(shí)現(xiàn)產(chǎn)品需求,達(dá)到盡快上線運(yùn)行的目的,采用單體式架構(gòu)方式開發(fā)。由于單體式架構(gòu)簡單,易于調(diào)試,只需要簡單運(yùn)行此應(yīng)用。易于部署,只需要把打包應(yīng)用拷貝到服務(wù)器端,通過負(fù)載均衡,在后端運(yùn)行多個(gè)副本,就可以輕松實(shí)現(xiàn)應(yīng)用擴(kuò)展。
前端頁面采用 angularJS1.0,前后端分離模式開發(fā)(其實(shí)是java程序員在做前端開發(fā))。既可以減少服務(wù)器渲染頁面消耗的性能,又兼顧java程序員的前端技術(shù)水平,減少前端頁面的開發(fā)難度。
項(xiàng)目上線之初,我們也面臨層層考驗(yàn),首先大量的js和html文件請求到tomcat,導(dǎo)致鏈接被耗盡,因此我們添加了自己的nginx服務(wù)器,將靜態(tài)資源部署在nginx上,不但減少了tomcat服務(wù)壓力,也讓我們的前后端分離開發(fā)更接近于標(biāo)準(zhǔn)化,為我們后期做微服務(wù)架構(gòu)改革打下基礎(chǔ)。其次大量的導(dǎo)出數(shù)據(jù)嚴(yán)重消耗了我們的服務(wù)器資源,因此我們設(shè)計(jì)了基于前端的下載,在服務(wù)器端不生成文件,改由ajax請求數(shù)據(jù),瀏覽器中組裝生成文件并保存,成功解決了這個(gè)問題。
不幸的是,單體式架構(gòu)有很大的局限性。應(yīng)用會隨著時(shí)間推移逐漸變大。由于業(yè)務(wù)的發(fā)展迅速,不到1年時(shí)間,我們那個(gè)小而簡單的應(yīng)用已經(jīng)成長為了龐然大物。此時(shí)的代碼復(fù)雜性高,整個(gè)項(xiàng)目包含的模塊非常多,依賴關(guān)系不清晰。
開發(fā)時(shí)啟動一次項(xiàng)目已經(jīng)需要3分鐘,這還不包含編譯的時(shí)間,開發(fā)電腦配置不好的話,會經(jīng)常導(dǎo)致卡頓甚至死機(jī),并且所有模塊代碼集中在一起,各模塊代碼提交時(shí)需要解決各種沖突,耗費(fèi)大量時(shí)間。
此時(shí)的開發(fā)團(tuán)隊(duì)很痛苦。開發(fā)和部署舉步維艱。而最嚴(yán)重問題是這個(gè)應(yīng)用太復(fù)雜,以至于沒有人能單獨(dú)搞定他。因此,修正bug和添加新功能變的非常困難,且耗時(shí)。由于不能快速的做出成績,整個(gè)開發(fā)團(tuán)隊(duì)都會變的消極。
而且我們的性能也達(dá)到了一定的瓶頸,所有的功能都堆積在一臺服務(wù)器上運(yùn)行,導(dǎo)致服務(wù)器硬件已經(jīng)不能很好的支撐如此多的業(yè)務(wù)代碼和數(shù)據(jù),硬件資源會產(chǎn)生很大的浪費(fèi),且性能很不穩(wěn)定,有許多宕機(jī)隱患。于是我們拆分了業(yè)務(wù)代碼,調(diào)整了部署方式,利用nginx反向代理,將不同的業(yè)務(wù)請求指向不同的服務(wù)器,處理不同的業(yè)務(wù)。
如圖所示,我們的每一個(gè)模塊都是可獨(dú)立運(yùn)行的項(xiàng)目,互相之間沒有依賴。采用了這種方法,我們以最小的成本,解決了性能上的燃眉之急(單體式架構(gòu)向垂直架構(gòu)的轉(zhuǎn)變)。
但是這樣的項(xiàng)目依然有一個(gè)很大的弊端,就是對于基礎(chǔ)功能,被其他功能引用的同一段代碼可能存在于多個(gè)項(xiàng)目中。代碼重復(fù)率高,維護(hù)難度大。一旦這些功能需要修改,則需要同時(shí)修改多個(gè)項(xiàng)目的代碼,并導(dǎo)致所有項(xiàng)目都要重新部署,成本非常高。
我們在業(yè)務(wù)功能相對穩(wěn)定的時(shí)候,投入了大量精力,重新調(diào)整了我們的架構(gòu)。采用微服務(wù)架構(gòu)方式,將神州系統(tǒng)按業(yè)務(wù)域劃分為多個(gè)服務(wù)。但是系統(tǒng)架構(gòu)的改造,不是一蹴而就的事情,我們將改造分為了三步執(zhí)行。
第一:制定新的系統(tǒng)框架
定義代碼規(guī)范,代碼工具等;
第二:停止向老的項(xiàng)目中添加功能,所有功能用新的框架開發(fā)及部署
當(dāng)單體式應(yīng)用龐大到無法管理時(shí),應(yīng)該停止讓其繼續(xù)變大,也就是說當(dāng)開發(fā)新功能時(shí)不應(yīng)該為舊單體應(yīng)用添加新代碼,最佳方法應(yīng)該是將新功能開發(fā)成獨(dú)立的微服務(wù);
第三:舊功能服務(wù)化
對舊的功能,根據(jù)業(yè)務(wù)需求以及系統(tǒng)開發(fā)需要,排期修改。每當(dāng)抽取一個(gè)模塊變成微服務(wù),單體應(yīng)用就變簡單一些;一旦轉(zhuǎn)換足夠多的模塊,單體應(yīng)用本身已經(jīng)不成為問題了,要么消失了,要么簡單到成為一個(gè)服務(wù)。
將單體應(yīng)用分解為多個(gè)微服務(wù),解決了單體應(yīng)用過于復(fù)雜的問題。使開發(fā)和維護(hù)變得更容易。服務(wù)內(nèi)部可以自由的設(shè)計(jì)解決方案,實(shí)現(xiàn)對外透明。即使重寫單個(gè)微服務(wù)也不會太困難,相比重寫整個(gè)單體應(yīng)用容易多了。每個(gè)微服務(wù)獨(dú)立部署,開發(fā)者不再需要協(xié)調(diào)其它服務(wù)部署對本服務(wù)的影響。這種改變可以加快部署速度,并且每個(gè)服務(wù)可以獨(dú)立擴(kuò)展。
微服務(wù)架構(gòu)中的每個(gè)服務(wù)都可以由專門的團(tuán)隊(duì)來開發(fā)。開發(fā)團(tuán)隊(duì)之間解耦,服務(wù)內(nèi)部獨(dú)立迭代,有利于充分利用人力資源,減少了團(tuán)隊(duì)管理的難度。
以上內(nèi)容都是實(shí)踐經(jīng)驗(yàn),交流促進(jìn)步,研討共成長,感謝大家耐心地閱讀,謝謝。
此文系作者個(gè)人觀點(diǎn),不代表羅戈網(wǎng)立場
-END-
瑪氏中國 | 2025年度國內(nèi)運(yùn)輸物流服務(wù)【冰淇淋業(yè)務(wù)】
4336 閱讀2025年京東物流貴州大件宅配、京東幫資源招商
2368 閱讀2025年京東物流-河北大件宅配、京東幫資源招商
1602 閱讀快運(yùn)網(wǎng)點(diǎn)的“跨境突破”:利潤更高、增長潛力大、協(xié)同增效
1169 閱讀“反內(nèi)卷”之后,快遞公司的“護(hù)城河”在哪?
1040 閱讀倉庫設(shè)計(jì)干貨:選址、布局、設(shè)計(jì)、設(shè)施……
1053 閱讀【權(quán)威發(fā)布】2025年貨車司機(jī)從業(yè)狀況調(diào)查報(bào)告(第一部分)
1017 閱讀順豐獲任大圩葡萄官方指定物流服務(wù)商
1016 閱讀京東在國內(nèi)首個(gè)大型折扣超市業(yè)態(tài)即將落地
946 閱讀順豐澳大利亞墨爾本新倉啟用
885 閱讀