本文旨在經過對某省高速公路聯網收費運營管理平臺的架構設計過程進行案例分析,描述架構設計的決策過程。數據庫
某省的高速公路分爲近百個路段,不一樣的路段歸屬不一樣的公司建設與運營,形成了車輛在跨越不一樣路段時,須要停經收費站繳費換卡,下降了高速公路的車輛通行效率。緩存
隨着信息化技術的發展,將全省的高速公路聯網收費的條件成熟,改造後車輛在高速公路上行駛,在出發地上高速時領卡,到目的地出高速時全程只需繳費一次。隨着信息化推動,將來車輛在全國範圍內高速公路通行,均只需繳費一次。安全
爲了適應全省聯網收費系統改造,迫切須要能集中對全部路段內的收費交易流水,高清卡口流水與圖像進行檢索,對交易流水進行從新拆分,對全省高速上車輛進行視頻監控與防逃費稽查。與之前最大的改進是數據由分散在各個路段系統,集中到省中心,並提供信息共享查詢與統計分析報表。服務器
根據業務需求,各個層級系統間數據流向以下圖所示:網絡
1) 全省路網約有100個路段中心;每一個路段中心對應幾個到幾十個不等的收費站,每一個收費站平均有4個入口車道,2個出口車道,合計全省約有2000個入口車道,1000個出口車道。多線程
2) 車輛駛入收費站上高速時,產生交易入口流水和高清卡口信息(包含圖像);車輛從收費站出口繳費時產生交易出口流水信息。各個車道中設備的狀態信息,定時發送到路段中心。架構
3) 各路段中心的數據須要及時彙總到省運營管理平臺。車輛從收費站出口繳費時,收費站系統須要到省運營平臺查詢該車輛對應的入口流水數據,以及高清卡扣流水數據,必要時還須要調取高清卡扣圖像進行肉眼比對。併發
4) 由省收費結算中心根據路段中心提供的交易流水進行費用拆分,並將拆分結果下發給省運營平臺。省運營平臺再將拆分結果下發給各個路段中心。負載均衡
5) 省運營平臺下發基礎費率、設備控制指令、運營參數信息到路段中心。路段中心再逐級下發到收費站。框架
對業務需求做進一步瞭解分析,發現系統具備以下特色:
1) 絕大多數場景對實時性要求不高。只有查詢入口交易流水須要在1秒內響應。
2) 系統的併發訪問量小。普通用戶數量小於2000。應用接口查詢併發數小於500。(在不考慮移動APP公衆應用的場景下)
3)複雜的業務邏輯少,系統需求集中於對數據進行查詢分析與信息管理。只有交易流水拆分規則較爲複雜。
4) 查詢入口交易流水與查詢高清卡口流水要求7 * 24高可用性,不然收費站程序可能會沒法對車輛進行收費計算處理,進行人工干預會大大下降收費效率,易形成交通堵塞。
5)交易流水與高清卡口流水數據量大,日均在3千萬和2千萬以上。業務管理上要求對交易流水存檔一年時間以上,高清卡口流水3個月以上。每張高清卡口圖片大小爲200K,集中存儲在省平臺將是巨大的容量。
在系統設計過程當中做重大決策,必須在分析清楚主要功能需求與質量性需求的基礎上,結合已有系統現狀,可支出經濟成本,技術團隊素質現狀,網絡環境,業務管理約束,工期要求等因素做出平衡性取捨。
在該系統的實施過程當中,最大的現實約束是工期趕,牽涉到的工程實施方多,開發測試時間被壓縮到2個月內,必須把握好進度不能影響其它單位聯調測試。在架構設計時必需要結合技術團隊現有的知識技能儲備,新技術預研須要成本,同時還會引入風險,必須謹慎。
因爲整個系統的業務功能很是多,劃分爲15個以上的子系統。對公共的用戶、組織機構、道路、收費站、基礎字典等信息放在一個數據庫(Schema)中,對其它業務系統不能公用的分別劃分一個數據庫。對於重點業務功能專門劃分一個數據庫。爲每個業務系統分配一個獨立的數據庫用戶,便於使用與管理。
充分利用Oracle數據庫其分區表機制,對於入口流水,出口流水,高清卡口流水等大表按照日期(例如按照3天,10天)進行分區,確保每一個分區內數據量在1億條之內。這樣在同一個分區內單表查詢時,只要數據庫索引創建合理,服務器資源充足,Oracle能保障在1秒內響應。同時在對歷史記錄作清理時可直接刪除分區文件,大數據量刪除性能獲得很大提高。
雖然已經對數據庫做了優化,但因爲車輛在收費出口繳費時,收費軟件均要查詢入口流水以及高清流水。若是併發查詢數上升,數據庫在處理併發查詢時就不必定能保證在1秒內響應了。該功能的響應性能,是用戶的痛點,直接決定了該項目被不被承認。
所以必須考慮引入NoSQL數據庫,將最近3天的流水數據加載到內存中,處理來自收費站的併發查詢請求,確保查詢在10~100毫秒內完成。
在咱們的業務場景中,數據已經持久化在Oracle中,引入分佈式緩存或NoSQL產品只是爲了直接從內存檢索數據提高性能。因而,對幾款開源的分佈式緩存和內存數據庫產品作了大體瞭解。
Memcached適合作分佈式緩存,但它自己不提供檢索查詢功能。它將數據所有放在內存中,不實現文件持久化機制。同時在集羣部署時,節點之間是不做通訊的,一旦某個節點宕機則該節點上數據所有丟失。要實現查詢檢索功能,應用開發的工做量會比較多,不適合咱們的場景。
Redis與MongoDB都提供了持久化到文件的機制,Redis的查詢性能優於MongoDB。但MongoDB在查詢API上實現了不少相似SQL語句查詢的便利功能,同時在集羣部署時它能自動實現數據分片,災難轉移,應用開發的工做量也要小一些。兩相比較,我的傾向於引入MongoDB的。可是苦於工期短,沒有人力與時間作深刻的預研,若是研究的不夠深刻,又會增長風險。
後來Vmware公司推薦一款叫GemFire的內存數據庫產品,稱在12306網站應用取得了不錯的效果。因而他們的售前就過來給咱們洗腦,演示了一些成功案例,讓咱們對這個產品增長了很大信心。讓我印象最深入的是這個產品定位爲內存計算平臺解決方案,能夠直接在數據節點進行計算(相似於在數據庫中預先定義好函數,在應用中進行調用),再將計算的結果合併後返回給應用,這就是分佈式計算的意思了。
因爲商業產品能夠提供可靠性保障,又能節約咱們的人力投入,項目預算也足夠,何樂而不爲。後面的實施狀況證實,這個產品性能與穩定性仍是不錯的,能將查詢時間下降到幾十毫秒級,固然也比較耗費內存與CPU(3臺服務器,每臺10G內存起)。
互聯網應用由於服務器規模龐大,爲了節約成本必須去IOE化,大量採用廉價服務器與開源軟件。企業應用由於規模小,相比之下,服務器資源沒有那麼大的規模,高配置的硬件成本企業還能負擔。該項目中採用IBM服務器,EMC存儲,思科的交換機,F5硬負載均衡器。
這種經過硬件來提高性能的方式,在成本容許的條件下,是能夠節省力氣的。採用了專用存儲,其自身已經作了冗餘機制,提供了災備的解決方案。應用層面就不用再去考慮數據災備的問題。硬盤壞了,就換個新硬盤插上去就行了,由於作了RAID10/5已經保證了數據不丟失。若等研究完幾個月的HDFS,終於敢用到項目裏面,項目工期已經結束了。
採用Oracle數據庫RAC集羣,提供了數據庫層面的高可用性。
採用IBM Websphere來部署重要業務系統,例如接口查詢子系統。它自身提供了軟負載均衡和集羣功能,可經過Web界面來對應用服務器集中管理與監控。這樣應用層的高可用也獲得瞭解決。(在咱們的重要業務場景中,接口查詢是無狀態的,會話不須要進行復制,也就是採用粘連性會話便可)。
業務場景中,省運營平臺還須要下發控制指令,運營參數等信息到各個路段。同時路段上傳的大量流水數據,若是先緩衝到消息服務器中,則拆分子系統能夠直接從消息服務器讀取數據,多線程處理或者單線程部署多份,部署模式很是靈活。同時引入消息中間件還能夠下降各個子系統的耦合度。
開源的有ActiveMQ、RabbitMQ,商用的也瞭解了下IBM MQ。比較詫異的是IBM MQ的併發性能測試指標很是差,比前二者都弱。
最終咱們採用了開源的RabbitMQ,看重的是它的併發性能和對於高可用以及災難轉移的支持。目前將服務端部署在省運營平臺,路段只使用客戶端進行鏈接。這樣也是考慮到部署與運維成本,路段的各合做方技術水平有限,分散部署不利於故障診斷。
通常大點的系統都有必要劃分紅多個子系統,易於團隊並行開發,部署升級也快。核心業務系統,咱們能夠集羣多部署一些實例,多給點硬件資源。不重要的業務系統,配置管理類的,甚至單實例部署,直接部署到Tomcat上。同時有些後臺服務,自己就是一個Java進程,與數據庫相關的,設計時就限定了只能部署一個實例。
子系統和子系統之間,能夠經過消息服務器來解耦,一個子系統宕機,不會影響另外的子系統運行。
在整個系統的實施過程當中,咱們引入了Portal門戶、統一用戶管理、單點登陸來進行不一樣Web之間頁面級的集成。
借鑑公司私有云建設的成功經驗(基於Vmware的產品組件),咱們認爲能夠經過對服務器進行虛擬化來充分利用資源,下降成本,也便於集中進行運維管理。
在實施過程當中,咱們將3臺豪華配置服務器虛擬出近百臺服務器,同時爲Oracle作集羣留下了2臺較高配置的服務器。
若是不進行虛擬化,可能須要更多的服務器,同時多個應用部署在一臺服務器上,運維監控起來很是麻煩。虛擬化後,能夠根據業務場景動態對服務器資源進行分配,這也是雲計算機的特色。
值得注意的是,在虛擬機上部署集羣應用時,要確保把節點分佈到不一樣的物理機器上,這樣才能真正保證高可用性。
前文提到,高清圖片數據量大,若集中存儲到省平臺耗費存儲容量。用專用存儲來存這些圖片,有些浪費。若將圖像從路段傳輸到省平臺,也將浪費大量的通訊帶寬。
實際業務場景中,收費站只在某些特定場景才調用圖像查詢接口,訪問量並不大。也就是說只有很是少的圖片真正須要被讀取。因而咱們定義了HTTP接口規範,由路段提供服務端實現,省平臺負責調用。由於HTTP接口簡單易於實現,給各路段增長的工做量很小。
也就是說,這裏咱們犧牲了圖像的查詢性能,節約了帶寬與存儲。
已有系統的接口方式都是經過中間數據庫來實現的,考慮到引入新的接口方式,路段太多,對合做公司的技術能力與集成工做量都將大大增長。因而咱們遵循了之前的方式,定義了中間表規範,由各個路段負責提供一套中間數據庫,往其中寫數據。
考慮到現有系統各類類型的數據庫都存在,因而咱們採用了開源數據抽取工具Kettle來進行數據遷移。同時數據庫抽取的數據量較大,各類不一樣的業務表結構,若是開發接口程序去實現,則工做量會很大,穩定性也是難以保證。
爲了保證數據抽取的效率,每10個路段分爲一組,部署一套Kettle抽取程序去作搬遷。
也就是說,這裏咱們考慮到現實技術條件,用最簡單適用的方式去實現業務功能。實際實施下來,這種數據抽取的方式爲項目節省了不少時間。
用戶與組織機構信息是存儲在公用數據庫中的。可是用戶的角色、可訪問的資源、以及資源URL等信息在各個子系統中是不同的。爲了提高性能,各個子系統將用戶和組織機構信息緩存到內存中,對於受權與訪問控制這塊的功能,經過代碼級別(class文件或者Jar包)的重用實現複用。
實際上,若是子系統數量愈來愈多,是能夠把用戶認證與受權以及查詢用戶信息這塊的功能服務化,包裝成HTTP REST服務或RPC調用服務。考慮到項目的工期,以及開發的成本,咱們並無這樣爲了技術而技術,直接經過數據庫訪問做接口和緩存用戶信息來提高性能。
注意這裏對用戶信息做緩存時必定要設置時效性,例如5分鐘。
下章節表述的是系統的總體架構,用來講明各個子系統及業務組件的劃分與所處的層次,還未細化到足以指導開發工做的程度。
1) 基礎設施層爲服務器、交換機、路由器、防火牆、安全防禦、磁帶備份等硬件網絡設備。還包括虛擬化軟件與操做系統。
2)中間件層爲商用的數據庫、應用服務器、內存數據庫以及開源的消息中間件、數據抽取軟件。
3) 服務組件層爲可複用的業務組件,二次開發框架。
4)業務應用層爲各個業務子系統。
1) Kettle將抽取到的流水數據存入數據庫,同時寫入到消息服務器RabbitMQ。
2)GemFire從流水數據庫裝載最近幾天的流水數據到內存。
3)接口查詢服務調用GemFire的客戶端API查詢入口流水。
4)交易流水拆分服務從消息服務器讀取數據進行處理,將拆分結果寫入業務數據庫。
5) 各個Web子業務系統須要依賴CAS服務實現單點登陸。
6)由統一用戶管理系統集中管理用戶與組織機構信息。
7)單點登陸服務從用戶數據庫查詢用戶信息以實現集中認證。
8)Portal門戶將各個Web子業務系統集成起來。
因爲子系統設計會涉及到公司具體的業務,這裏不作進一步描述。設計時只要按照通用功能抽取,不一樣業務功能劃分不一樣子系統原則便可。
一般子系統設計中須要描述清楚具體的功能模塊設計,業務處理流程,開發包劃分,領域模型,關鍵的類圖,內部接口及外部接口的規範。
玩過即時戰略類電子遊戲的朋友,都知道何時採礦,幾個農民採一堆最大效率,何時造什麼兵種來剋制對方,何時偵查與擴張,做戰時候多兵種如何擺陣配合才能發揮最佳優點。這裏不妨做一下類比,架構設計就是實施戰略的過程,具體的技術是兵種武器,模式理論就是各類戰術。