服务架构演进
服務架構演進
單一應用架構
當網(wǎng)站流量很小時,只需一個應用,將所有功能都部署在一起,以減少部署節(jié)點和成本。
此時,用于簡化增刪改查工作量的 數(shù)據(jù)訪問框架(ORM) 是關鍵。
垂直應用架構
當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆成互不相干的幾個應用,以提升效率。
此時,用于加速前端頁面開發(fā)的 Web框架(MVC) 是關鍵。
分布式服務架構
當垂直應用越來越多,應用之間交互不可避免,將核心業(yè)務抽取出來,作為獨立的服務,逐漸形成穩(wěn)定的服務中心,使前端應用能更快速的響應多變的市場需求。
此時,用于提高業(yè)務復用及整合的 分布式服務框架(RPC) 是關鍵。
流動計算架構
當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現(xiàn),此時需增加一個調度中心,基于訪問壓力實時管理集群容量,提高集群利用率。
此時,用于提高機器利用率的 資源調度和治理中心(SOA) 是關鍵。
如圖:
服務治理過程演進
在大規(guī)模服務化之前,應用可能只是通過RMI或Hessian等工具,簡單的暴露和引用遠程服務,通過配置服務的URL地址進行調用,通過F5等硬件進行負載均衡。
(1) 當服務越來越多時,服務URL配置管理變得非常困難,F5硬件負載均衡器的單點壓力也越來越大。
此時需要一個服務注冊中心,動態(tài)的注冊和發(fā)現(xiàn)服務,使服務的位置透明。
并通過在消費方獲取服務提供方地址列表,實現(xiàn)軟負載均衡和Failover,降低對F5硬件負載均衡器的依賴,也能減少部分成本。
(2) 當進一步發(fā)展,服務間依賴關系變得錯蹤復雜,甚至分不清哪個應用要在哪個應用之前啟動,架構師都不能完整的描述應用的架構關系。
這時,需要自動畫出應用間的依賴關系圖,以幫助架構師理清理關系。
(3) 接著,服務的調用量越來越大,服務的容量問題就暴露出來,這個服務需要多少機器支撐?什么時候該加機器?
為了解決這些問題,第一步,要將服務現(xiàn)在每天的調用量,響應時間,都統(tǒng)計出來,作為容量規(guī)劃的參考指標。
其次,要可以動態(tài)調整權重,在線上,將某臺機器的權重一直加大,并在加大的過程中記錄響應時間的變化,直到響應時間到達閥值,記錄此時的訪問量,再以此訪問量乘以機器數(shù)反推總容量。
(4) 規(guī)模繼續(xù)擴大,應用之間不再是扁平的對應關系,開始分層,比如核心數(shù)據(jù)層,業(yè)務集成層等,就算沒有出現(xiàn)循環(huán)依賴,也不允許從低層向高層依賴,以免后續(xù)被逼循環(huán)依賴。
這時,需要在注冊中心定義架構體系,列明有哪些層的定義,每個服務暴露或引用時,都必須聲明自己應用屬于哪一層,這樣注冊中心能更快的發(fā)現(xiàn)架構的腐化現(xiàn)象。
(5) 服務多了,溝通成本也開始上升,調某個服務失敗該找誰?服務的參數(shù)都有什么約定?
這時就需要登記每個服務都是誰負責的,并建立一個服務的文檔庫,方便檢索。
(6) 慢慢一些敏感數(shù)據(jù)也都服務化了,安全問題開始變得重要,誰能調該服務?如何授權?
這樣的服務可能需要一個密碼,訪問時需帶著此密碼,但如果用密碼,要改密碼時,就會很不方便,所有的消費方都要改,所以動態(tài)生成令牌(Token)可能會更好,提供方將令牌告之注冊中心,由注冊中心決定是否告之消費方,這樣就能在注冊中心頁面上做復雜的授權模型。
(7) 就算是不敏感的服務,也不是能任意調用,比如某服務突然多了一個消費者,這個消費者的請求量直接把服務給拖跨了,其它消費者跟著一起故障。
首先服務提供方需要流控,當流程超標時,能拒絕部分請求,進行自我保護。
其次,消費者上線前和提供者約定《服務質量等級協(xié)定(SLA)》,SLA包括消費者承諾每天調用量,請求數(shù)據(jù)量,提供方承諾響應時間,出錯率等,將SLA記錄在監(jiān)控中心,定時與監(jiān)控數(shù)據(jù)對比,超標則報警。
(8) 雖然有SLA約定,如果不能控制,就只是君子協(xié)定,如何確保服務質量?
比如:一個應用很重要,一個不那么重要,它們調用同一個服務,這個服務就應該向重要應用傾斜,而不是一視同仁,當支撐不住時,應限制不重要應用的訪問,保障重要應用的可用,如何做到這一點呢。這時,就需要服務路由,控制不同應用訪問不同機器,比如:
應用分離:
consumer.application = foo => provider.host = 1,2,3
consumer.application != foo => provider.host = 5,6
讀寫分離:
method.name = find*,get* => provider.host = 1,2,3
method.name != find*,get* => provider.host = 5,6
(9) 服務上線后,需要驗證服務是否可用,但因防火墻的限制,線下是不能訪問線上服務的,不得不先寫好一個測試Main,然后放到線上去執(zhí)行,非常麻煩,并且容易忘記驗證。
所以線上需要有一個自動運行的驗證程序,用戶只需在界面上填上要驗證的服務方法,以及參數(shù)值和期望的返回值,當有一個服務提供者上線時,將自動運行該用例,并將運行結果發(fā)郵件通知負責人。
(10) 服務應用和Web應用是有區(qū)別的,它是一個后臺Daemon程序,不需要Tomcat之類的Web容器。但因公司之前以Web應用為主,規(guī)范都是按Web應用的,所以不得不把服務跑在一個根本用不上的Web容器里,而搭一個這樣的Web工程也非常費事。
所以需要實現(xiàn)一個非Web的容器,只需簡單的Main加載Spring配置即可,并提供Maven模板工程,只需mvn dubbo:generate 即可創(chuàng)建一個五臟俱全的服務應用。
(11) 開發(fā)服務的人越來越多,更注重開發(fā)效率,IDE的集成支持必不可少。
通過插件,可以在Eclipse中直接運行服務,提供方可以直接填入測試數(shù)據(jù)測試服務,消費方可以直接Mock服務不依賴提供方開發(fā)。
(12) 因為暴露服務很簡單,服務的上線越來越隨意,有時候負責服務化的架構師都不知道有人上線了某個服務,使得線上服務魚龍混雜,甚至出現(xiàn)重復的服務,而服務下線比上線還困難。
需要一個新服務上線審批流程,必須經(jīng)過服務化的架構師審批過了,才可以上線。
而服務下線時,應先標識為過時,然后通知調用方盡快修改調用,直到?jīng)]有人調此服務,才能下線。
(13) 因服務接口設計的經(jīng)驗一直在慢慢的積累過程中,很多接口并不能一促而蹴,在修改的過程中,如何保證兼容性,怎么判斷是否兼容?另外,更深層次的,業(yè)務行為兼容嗎?
可以根據(jù)使用的協(xié)議類型,分析接口及領域模型的變更是否兼容,比如:對比加減字段,方法簽名等。
而業(yè)務上,可能需要基于自動回歸測試用例,形成Technology Compatibility Kit (TCK),確保兼容升級。
(14) 隨著服務的不停升級,總有些意想不到的事發(fā)生,比如cache寫錯了導致內(nèi)存溢出,故障不可避免,每次核心服務一掛,影響一大片,人心慌慌,如何控制故障的影響面?服務是否可以功能降級?或者資源劣化?
應用間聲明依賴強度,哪些功能強依賴,哪些弱依賴,然后基于依賴強度,計算出影響面,并定期測試復查,加強關鍵路徑上的服務的優(yōu)化和容錯,清理不該在關鍵路徑上的服務。
提供容錯Mock數(shù)據(jù),Mock數(shù)據(jù)也應可以在注冊中心在運行時動態(tài)下發(fā),當某服務不可用時,用Mock數(shù)據(jù)代替,可以減少故障的發(fā)生,比如某驗權服務,當驗權服務全部掛掉后,直接返回false表示沒有權限,并打印Error日志報警。
另外,前端的頁面也應采用Portal進行降級,當該Portal獲取不到數(shù)據(jù)時,直接隱藏,或替換為其它模塊展示,并提供功能開關,可人工干預是否展示,或限制多少流量可以展示。
(15) 當已有很多小服務,可能就需要組合多個小服務的大服務,為此,不得不增加一個中間層,暴露一個新服務,里面分別調其它小服務,這樣的新服務業(yè)務邏輯少,卻帶來很多開發(fā)工作量。
此時,需要一個服務編排引擎,內(nèi)置簡單的流程引擎,只需用XML或DSL聲明如何聚合服務,注冊中心可以直接下發(fā)給消費者執(zhí)行聚合邏輯,或者部署通用的編排服務器,所有請求有編排服務器轉發(fā)。
(16) 并不是所有服務的訪問量都大,很多的服務都只有一丁點訪問量,卻需要部署兩臺提供服務的機器,進行HA互備,如何減少浪費的機器。
此時可能需要讓服務容器支持在一臺機器上部署多個應用,可以用多JVM隔離,也可以用ClassLoader隔離。
(17) 多個應用如果不是一個團隊開發(fā)的,部署在一臺機器上,很有可以誤操作,停掉了別人的服務。
所以需要實現(xiàn)自動部署,所有的部署都無需人工干擾,最好是一鍵式部署。
(18) 機器總是的閑時和忙時,或者冗余機器防災,如何提高機器的利用率?
即然已經(jīng)可以自動部署了,那根據(jù)監(jiān)控數(shù)據(jù),就可以實現(xiàn)資源調度,根據(jù)應用的壓力情況,自動添加機器并部署。
如果你的應用是國際化的,有中文站,美國站之類,因為時差,美國站的機器晚上閑的時候,可能正是中文站的白天忙時,可以通過資源調度,分時段自動調配和部署雙方應用。
按關鍵詞歸納為:
服務注冊與發(fā)現(xiàn)
軟負載均衡與容錯
服務監(jiān)控與統(tǒng)計
服務容量評估
服務上線審批
服務下線通知
服務負責人
服務文檔
服務路由
服務編排
服務黑白名單
服務權限控制
服務依賴關系
服務分層架構
服務調用鏈跟蹤
故障傳導分析
服務降級
服務等級協(xié)定
服務自動測試
服務偽裝容錯
服務兼容性檢測
服務使用情況報告
服務權重動態(tài)調整
服務負載均衡調整
服務映射
服務模板工程
服務開發(fā)IDE
服務健康檢測
服務容器
服務自動部署
服務資源調度
總結
- 上一篇: 为什么不用ZK来做服务发现?
- 下一篇: 服务降级及dubbo中的实现示例