關(guān)于架構(gòu),筆者認(rèn)為并不是越復(fù)雜越好,而是相反,簡單就是硬道理也提現(xiàn)在這里。這也是微服務(wù)能夠流行的原因,看看市場上曾經(jīng)出現(xiàn)的服務(wù)架 構(gòu):EJB、SCA、Dubbo等等,都比微服務(wù)先進,都比微服務(wù)功能完善,但它們都沒有微服務(wù)這么深入民心,就是因為他們過于復(fù)雜。簡單就是高科技,蘋 果手機據(jù)說專門有個團隊研究如何能讓用戶更加簡單的操作。大公司都是由小公司發(fā)展起來的,如果小公司在開始技術(shù)選型時感覺某個框架費時費力就不會選擇,而 小公司發(fā)展到大公司的過程,一般也伴隨著系統(tǒng)不斷優(yōu)化的過程,而不斷優(yōu)化往往不會重新選擇開發(fā)技術(shù)和框架,而是在原來基礎(chǔ)改進,這也許就是簡單框架流行的 本質(zhì)。 假設(shè)我們需要為超高業(yè)務(wù)量的保險代理企業(yè)設(shè)計一個“互聯(lián)網(wǎng)+”保險平臺。假設(shè)這家保險代理企業(yè)網(wǎng)上保險注冊用戶規(guī)模為2千萬,門店及加盟商銷售 人員2萬,年保單量2億單(中國平安總用戶規(guī)模達1.67億,擁有超過79.8萬名壽險銷售人員和約24.6萬名正式雇員。截至2015年6月30日,集 團總資產(chǎn)達4.63萬億元,歸屬母公司股東權(quán)益為3,311.90億元。而目前互聯(lián)網(wǎng)保險領(lǐng)頭羊眾安保險,經(jīng)營以小額貸款為主,由于背靠阿里巴巴,日保單 銷售量可達1億,不過別人很難復(fù)制眾安保險的模式)。因此我們?nèi)〈笮突ヂ?lián)網(wǎng)企業(yè)和眾安保險的折衷來考慮這個保險O2O平臺。 l 需求分析 參考保險業(yè)務(wù)相關(guān)文檔(文檔不全),獲得如下核心需求矩陣(因為涉及功能太多,只取大的功能點)。
從O2O的概念來看:“O2O即Online To Offline,也即將線下商務(wù)的機會與互聯(lián)網(wǎng)結(jié) 合在了一起,讓互聯(lián)網(wǎng)成為線下交易的前臺。這樣線下服務(wù)就可以用線上來攬客,消費者可以用線上來篩選服務(wù),還有成交可以在線結(jié)算,很快達到規(guī)模。該模式最 重要的特點是:推廣效果可查,每筆交易可跟蹤(百度百科)”,不是每一種服務(wù)都適合O2O。商品類的銷售不適合O2O,因為你直接從網(wǎng)店就可以購買根本不 需要線下店。但保險類服務(wù)的確需要線下和線上結(jié)合,如果是純線上將不能滿足客戶的服務(wù)需求。O2O的線下服務(wù)可以是加盟商、代理人,也可以是直營店。 上面的需求是按照用戶角度提出的,雖然使用“系統(tǒng)”一詞,但這里的系統(tǒng)是一個抽象概念,可能包括軟件系統(tǒng)以及人事、制度等在內(nèi)。上面的需求可以 分為三大類,一類是針對終端用戶純線上服務(wù):電子商務(wù)網(wǎng)站(B2C);一類是專門針對代理人服務(wù)的:代理人系統(tǒng);剩下的是一些公共服務(wù),有可能電子商務(wù)網(wǎng) 站和代理人系統(tǒng)都會用到的一些服務(wù)。另外保險業(yè)務(wù)最大的一個問題是多個險種,不同險種處理方式有很大不同,這跟普通電子商務(wù)網(wǎng)站區(qū)別很大,比如天貓,所有 商品都是同樣的下單方式,同樣售后服務(wù)(主要就是快遞這塊),而保險產(chǎn)品即使是線上B2C網(wǎng)站下單操作,短險、壽險、車險等也是不同的,更何況保險有一大 堆售后服務(wù),這些售后服務(wù)更加不相同。傳統(tǒng)保險公司在處理這方面時,一般會做多個系統(tǒng),比如壽險系統(tǒng),車險系統(tǒng)等等。 l 系統(tǒng)分析 安裝之前提到的業(yè)務(wù)規(guī)模我們分析(假設(shè))出一些比較重要的性能需求: a)產(chǎn)品方面:繼續(xù)上線當(dāng)前沒有的保險產(chǎn)品 b)B2C網(wǎng)站日訪問量:5000萬PV c)B2C產(chǎn)品購買并發(fā)高峰:2000 TPS d)運維系統(tǒng)同時在線:1萬(共有2萬銷售員或代理人) e)運維系統(tǒng)并發(fā)高峰:2000 TPS f)短險訂單:每年1.85億單 g)長險訂單:每年500萬 h)車險訂單:每年1000萬 i)案卷信息:每年新增100萬單 日訪問量5000萬和產(chǎn)品并發(fā)2000 TPS是我們假設(shè)的,客戶信息和案卷信息是隨訂單數(shù)據(jù)量變化而變化,在前面我們雖然假設(shè)了總共每年產(chǎn)生2億個訂單,但是根據(jù)保險種類,短險(旅游險、傷殘 險)明顯產(chǎn)生了90%的訂單量,這一點需要特殊處理。除此之外車險和長險(主要指壽險等)無論是投保還是售后服務(wù)都有明顯不同,所以也需要特殊處理。 那么我們按照上面的需求,進行系統(tǒng)分析,首先按大的職責(zé)將職責(zé)相同的劃分為一個服務(wù)。并且有了上面這個性能需求,所有功能需求都需要增加一項 “質(zhì)量”特性,那就是“高并發(fā)”,高并發(fā)會影響到所有設(shè)計。另外如果要將互聯(lián)網(wǎng)保險平臺質(zhì)量特性排個序,最重要的是可擴展性、安全性,因為保險的種類多而 且處理方式不同,除此之外,高并發(fā)和可靠性也會直接影響功能的實現(xiàn),但并沒有可擴展性影響大。深入分析職責(zé)后把每一種功能的實現(xiàn)關(guān)鍵技術(shù)列出,如下:
各個子系統(tǒng)及模塊的關(guān)系如下圖。 其中訂單服務(wù)、產(chǎn)品服務(wù)、財務(wù)服務(wù)、工具服務(wù)為基礎(chǔ)服務(wù),其它各個業(yè)務(wù)模塊的服務(wù)會調(diào)用這些基礎(chǔ)服務(wù)。各個業(yè)務(wù)模塊的服務(wù)都是根據(jù)業(yè)務(wù)領(lǐng)域進行劃分的,同 一業(yè)務(wù)領(lǐng)域下實現(xiàn)技術(shù)不同會被劃分為兩個服務(wù),比如產(chǎn)品展示和訂單原本屬于同一個大的領(lǐng)域,但其因為實現(xiàn)技術(shù)和質(zhì)量要求不同需要劃分為兩個服務(wù)。因為短險 接入量大,而且大部分是跟第三方合作接入,因此設(shè)計短險接入公共接口服務(wù)平臺處理大量短險訂單。 l 存儲及緩存架構(gòu) 對于大型的高并發(fā)系統(tǒng)來講,最重要的當(dāng)屬數(shù)據(jù)的架構(gòu)。我們在前面也提到過,web系統(tǒng)業(yè)務(wù)處理模塊本身就可以集群部署,當(dāng)用戶出現(xiàn)高并發(fā)時最先 遇到的瓶頸就是數(shù)據(jù)庫訪問的瓶頸。這也是我們說數(shù)據(jù)架構(gòu)最為重要的原因。其實web系統(tǒng)是典型的“計算機信息系統(tǒng)”,也就是說一切以數(shù)據(jù)(信息)為基礎(chǔ), 所有的功能都是圍繞著數(shù)據(jù)來的。這也是我們在這里說數(shù)據(jù)是web系統(tǒng)最重要的,很多公司在做少用戶量web系統(tǒng)時直接設(shè)計好數(shù)據(jù)庫就可以開發(fā)了。 按照上面劃分的業(yè)務(wù)領(lǐng)域我們設(shè)計多個數(shù)據(jù)庫,技術(shù)選項包括“是否讀寫分離”、“是否水平切分”及“路由鍵”。其中路由鍵是指在進行水平切分后,我們使用那個“標(biāo)識”去查詢數(shù)據(jù)庫,一般來說會使用該業(yè)務(wù)領(lǐng)域聚合根對象的主鍵作為路由鍵。
除工具數(shù)據(jù)庫外,其它的數(shù)據(jù)庫的劃分很容易理解。工具數(shù)據(jù)庫的數(shù)據(jù)也大都跟客戶或說用戶有關(guān),比如“產(chǎn)品對接服務(wù)”,產(chǎn)品對接服務(wù)是指用戶在購買了保單 后,系統(tǒng)會自動對接到具體的保險公司接口去上傳保單信息和下載保單,所以水平切分?jǐn)?shù)據(jù)庫時可以采用用戶ID作為路由鍵?!霸诰€支付”和“通知服務(wù)”也是類 似,都是保存用戶相關(guān)的數(shù)據(jù),在線支付服務(wù)保存的是用戶在線支付的流水,通知服務(wù)保存的是發(fā)送給某用戶的短信或郵件。 另外在數(shù)據(jù)架構(gòu)中我們也可以看到一個規(guī)律,就是使用了水平分庫的存儲結(jié)構(gòu)就不能再使用讀寫分離,原因是防止存儲單元過度泛濫,因為使用了水平分庫之后,本 身也要為數(shù)據(jù)庫建立多個備份庫,這個時候如果再用讀寫分離需要建立一套只讀庫,數(shù)據(jù)庫的數(shù)量將增加一倍。使用了分庫后我們可以把熱點數(shù)據(jù)存儲在分布式緩存 中以起到讀寫分離類似的作用。 另外緩存也是存儲技術(shù)的一種,而且非常重要。從日常生活中我們也可以看到這一點。比如你要去購買一臺電腦,你會發(fā)現(xiàn)二級緩存和內(nèi)存大的價格高出很 多,如果你的顯卡顯存巨大,那將是頂級配置,發(fā)燒級配置。手機也是一樣,內(nèi)存大的手機速度明顯快,價格也高,如果內(nèi)存和持久化存儲都高,那也是頂級配置。 對于web系統(tǒng)也是一樣,有些大型web系統(tǒng)只要緩存處理的好,數(shù)據(jù)庫不需要分庫就可以承載億級的用戶,比如維基百科、新浪微博等。也因此,不管是電子商 務(wù)網(wǎng)站還是互聯(lián)網(wǎng)+大型應(yīng)用,都會在它們的架構(gòu)中看到緩存大量使用的情況。 從整個web系統(tǒng)的架構(gòu)來看,緩存在兩個層面大量使用,分別是展示層和邏輯層,展示層通常使用高速的頁面緩存,邏輯層通常使用高并發(fā)的分布式緩存。當(dāng)然有些分布式緩存工具既可以在邏輯層使用也可以在顯示層使用。
l 邏輯架構(gòu) 在給出系統(tǒng)總體的邏輯架構(gòu)前,我們先看看系統(tǒng)前端和服務(wù)層直接的關(guān)系。前端是客戶端,可以有多個客戶端,也可以有多種客戶端,比如手機端 (APP、WAP、微信)等??蛻舳撕头?wù)之間的架構(gòu)是典型的MVC架構(gòu),V是客戶端,C就是spring mvc或servlet開發(fā)的控制層,對于Web應(yīng)用V和C在開發(fā)角度是一個工程,剩下的M就是服務(wù)層。這是對于web系統(tǒng)來說的,對于app或者使用 html直接實現(xiàn)的客戶端,或者是.net實現(xiàn)的桌面客戶端,由于這些客戶端是單獨開發(fā)的,沒有控制層,因此需要增加一層“API 網(wǎng)關(guān)”作為這些客戶端的控制層。 圖中的服務(wù)組件就是指各個業(yè)務(wù)服務(wù),這些服務(wù)可以看成是組件的概念。通常前端界面一個界面中需要的數(shù)據(jù)通常不僅僅來自于同一個服務(wù),即使是來自于同 一個服務(wù),那也來自于很多不同的接口,servlet或api 網(wǎng)關(guān)作為控制層,所起到的作用就是組合接口、組合數(shù)據(jù),并處理接口間的事務(wù)性。另外服務(wù)組件也是分層的,圖中并沒有展現(xiàn),一般可以分為3層,從低到高依次 是工具性服務(wù)組件、基礎(chǔ)業(yè)務(wù)層服務(wù)組件、業(yè)務(wù)層服務(wù)組件。前端界面的請求按照從高到底向下傳遞和處理請求。 按照職責(zé)、通用性、技術(shù)特性綜合考慮和計量,邏輯架構(gòu)設(shè)計如下圖: 十幾個子系統(tǒng)分別分布在服務(wù)層、控制層、表現(xiàn)層(典型的三層架構(gòu))。實體層和接口訪問層雖然屬于“層”,但 它們并不單獨發(fā)布,而是使用Jar包類庫的方式提供給其它服務(wù)調(diào)用,是邏輯上的層。服務(wù)組件的構(gòu)成大都是按照業(yè)務(wù)領(lǐng)域劃分的,只有一個除外,就是“B2C 網(wǎng)站”,B2C網(wǎng)站由于是面向終端用戶的高并發(fā)電子商務(wù)網(wǎng)站,為了處理高并發(fā),我們將其拆分為兩個業(yè)務(wù)領(lǐng)域(也可以拆分成多個業(yè)務(wù)領(lǐng)域,看實際并發(fā)量), 分別是用戶賬戶和產(chǎn)品。用戶瀏覽產(chǎn)品并購買,這是電子商務(wù)網(wǎng)站最基本的兩個領(lǐng)域。其中產(chǎn)品瀏覽等功能由更底層的產(chǎn)品服務(wù)提供,用戶賬戶功能由會員服務(wù)提 供。還有一些功能,比如推薦商品可能是由其它服務(wù)提供,這些可以在控制層直接組合這些服務(wù)。 l 服務(wù)架構(gòu) 服務(wù)框架采用典型的“服務(wù)注冊表”模式,注冊表使用redis。服務(wù)組件在啟動時將自己注冊進服務(wù)注冊表,web服務(wù)器或api 網(wǎng)關(guān)在訪問服務(wù)時查詢服務(wù)注冊表得到服務(wù)的uri,然后調(diào)用某服務(wù)接口。
淘寶的dubbo使用的是zookeeper作為服務(wù)注冊表,之所以使用zookeeper,主要是使用它的負(fù)載均衡的功能。筆者認(rèn)為restful接口 沒有必要使用zookeeper做負(fù)載均衡,可以使用nginx(負(fù)載均衡服務(wù)器都可以),所以沒必要選用動態(tài)的zookeeper作為注冊表,而是使用 “redis+心跳監(jiān)測”機制(redis也可以換為LDAP等)來完成服務(wù)注冊和監(jiān)控失效服務(wù)的功能。這個方案至少比dubbo簡單幾個數(shù)量級,簡單就 是硬道理。 在注冊服務(wù)時只需要注冊nginx服務(wù)器的IP以及服務(wù)描述信息即可。反觀dubbo還要注冊接口進注冊表,筆者認(rèn)為這個沒必要,因為調(diào)用一個服務(wù) 接口的充分必要條件就是知道服務(wù)器的IP即可。至于調(diào)用什么服務(wù)接口,肯定在代碼里已經(jīng)寫死,目標(biāo)服務(wù)器必定存在這個服務(wù)接口。將服務(wù)接口注冊進服務(wù)注冊 表如果是為了監(jiān)控審計服務(wù)的使用情況,那這個功能使用訪問日志來實現(xiàn)能做的更好。 總體的分布式拓補結(jié)構(gòu)如下圖: 對于服務(wù)集群來講,看上去像是一個大哥(nginx)帶有眾多小弟的結(jié)構(gòu)。訪問某服務(wù)群組只需要訪問其nginx服務(wù)器即可,這里nginx均采用高可用 方案,防止單臺nginx出現(xiàn)問題。至于高層服務(wù)調(diào)用底層服務(wù)也是直接訪問其服務(wù)器組的nginx。這個執(zhí)行的流程其實和日常生活中的概念很像,如公司內(nèi) 部的執(zhí)行流也是如此:老板分配任務(wù)給部門經(jīng)理,部門經(jīng)理分配任務(wù)給主管,主管分配任務(wù)給具體的個人(某單臺服務(wù)器)。領(lǐng)導(dǎo)們起到的作用也是負(fù)載均衡和監(jiān) 控,負(fù)載均衡就是把任務(wù)可以分配給多個人同時執(zhí)行(并且某個執(zhí)行失敗自動切換),監(jiān)控就不必說了就是監(jiān)控任務(wù)完成情況。在我們的方案里,會專門有個服務(wù)去 監(jiān)控所有服務(wù)器的執(zhí)行情況,很簡單的服務(wù)就可以做到。 l 關(guān)于分布式事務(wù) 如果研究一下EJB就會發(fā)現(xiàn),EJB和微服務(wù)的架構(gòu)基本相同,甚至所有面向服務(wù)(SCA、SOA等等)的架構(gòu)都相差不大。很多人反對EJB,并 不是EJB不夠強大,而是它不夠簡單,它給項目帶來的復(fù)雜性甚至超過了項目本身(這也是筆者不建議使用dubbo框架的原因)。曾有人說過:你要么把事情 做的盡可能簡單,讓人挑不出毛?。灰窗咽虑樽龅谋M可能復(fù)雜,讓人找不出毛病,EJB就是后者。EJB分布式事務(wù)機制實現(xiàn)的很好,可惜的是這種“一刀切” 的事務(wù)機制,大大降低了web系統(tǒng)的性能,所以幾乎所有面向互聯(lián)網(wǎng)的應(yīng)用都極少使用分布式事務(wù),也就不會采用EJB。互聯(lián)網(wǎng)應(yīng)用本身事務(wù)性操作并不多,一 些新聞、博客之類的網(wǎng)站甚至都不需要事務(wù)。另外一個方面,即使出現(xiàn)一個或兩個分布式事務(wù)應(yīng)用場景,也可以通過其它手段解決,比如事件機制等等。 在之前的文章中我們也提到過對于分布式事務(wù)最佳的策略是盡量避免。如果避免不了將按以下方式實現(xiàn)。 1) 將分布式事務(wù)性操作封裝在一個服務(wù)中,這個服務(wù)使用XA或鏈?zhǔn)椒植际绞聞?wù)管理。 2) 可以使用事件機制協(xié)調(diào)事務(wù)管理(具體做法就是事務(wù)失敗后發(fā)失敗事件到可持久化的消息隊列,然后需回滾操作的接口監(jiān)控此事件并執(zhí)行回滾)。 3) 使用自定義分布式事務(wù)管理器管理分布式事務(wù)。 筆者設(shè)想的自定義分布式事務(wù)管理器主要是封裝了流程及分布式事務(wù)相關(guān)功能,筆者將在其它文章專門討論。如圖所示,假設(shè)有一個事務(wù)需要依次調(diào)用 ABCDE五個接口,我們首先調(diào)用分布式事務(wù)管理接口創(chuàng)建這條“流程”的實例,實例中五個接口分別對應(yīng)五個狀態(tài),調(diào)用成功后將該接口對應(yīng)的狀態(tài)設(shè)置為“成 功”,反之就是“失敗”,流程處理結(jié)束后,分布式事務(wù)檢查狀態(tài),然后按照一定的策略調(diào)用失敗接口的反向操作接口去回滾數(shù)據(jù)(前提條件也是參與分布式事務(wù)操 作的接口要開發(fā)反向操作接口)。這既是一個簡單的流程引擎,也是一個分布式事務(wù)協(xié)調(diào)處理裝置,具體是否有必要做的復(fù)雜(比如處理并行流程),還要看實際環(huán) 境下分布式事務(wù)的情況,但筆者認(rèn)為互聯(lián)網(wǎng)前端應(yīng)用使用簡單流程應(yīng)該足以應(yīng)付。 l 開發(fā)架構(gòu) 系統(tǒng)所需的工程,“[ ]”里面表示工程的名稱。 從圖中不難看出,我們將運維相關(guān)前端界面合并為一個前端系統(tǒng),總體來講前端只有3種,B2C前端、APP前端、運維前端。把運維前端合并為一個 項目有利于加快前期的開發(fā)、部署的效率,在后期如果某子系統(tǒng)功能界面太多,可以將前端系統(tǒng)獨立,比如公估系統(tǒng)、客戶管理系統(tǒng)等,獨立后的系統(tǒng)需要使用單點 登錄,這樣就可以在各個系統(tǒng)之間免登陸切換。 開發(fā)環(huán)境: 編碼:UTF-8 工具:Myeclipse 10 SVN:Site-1.8.22 Web服務(wù)器:Tomcat7 JDK: JDK1.7、 Java EE 5 開發(fā)環(huán)境:Maven 3 開發(fā)技術(shù)選型: 表現(xiàn)層:Bootstrap+Html+Jquery MVC框架:Spring MVC 3.2 安全框架:Spring security 3.2 Rest接口實現(xiàn):Spring MVC Rest 持久層:Mybatis3.2 分布式緩存:Redis 數(shù)據(jù)庫:MySql 5.6 【編輯推薦】 【責(zé)任編輯:wangxueyan TEL:(010)68476606】
|
|