Dubbo框架應用之(二)--服務治理

Dubbo服務治理全貌圖





       當我們現有ITOO平臺系統的業務隨着用戶的逐漸增大,設計的業務越來越廣,系統會異常的複雜,在大規模服務之前,我們可以採用的是RMI或Hessian等工具,暴露和引用遠程服務,通過配置URL地址和JNDI地址進行調用,使用Apache httpd複雜均衡插件或F5服務器進行負載均衡


存在以下問題和如何解決呢?


       當服務越來越多時,服務URL配置管理變得非常困難,F5硬件負載均衡器的單點壓力也越來越大。

       此時需要一個服務註冊中心,動態的註冊和發現服務,使服務的位置透明。

並通過在消費方獲取服務提供方地址列表,實現軟負載均衡和Failover,降低對F5硬件負載均衡器的依賴,也能減少部分成本。


        當進一步發展,服務間依賴關係變得錯蹤複雜,甚至分不清哪個應用要在哪個應用之前啓動,架構師都不能完整的描述應用的架構關係。

      這時,需要自動畫出應用間的依賴關係圖,以幫助架構師理清理關係。


       接着,服務的調用量越來越大,服務的容量問題就暴露出來,這個服務需要多少機器支撐?什麼時候該加機器?

       爲了解決這些問題,第一步,要將服務現在每天的調用量,響應時間,都統計出來,作爲容量規劃的參考指標。

其次,要可以動態調整權重,在線上,將某臺機器的權重一直加大,並在加大的過程中記錄響應時間的變化,直到響應時間到達閥值,記錄此時的訪問量,再以此訪問量乘以機器數反推總容量。


        規模繼續擴大,應用之間不再是扁平的對應關係,開始分層,比如核心數據層,業務集成層等,就算沒有出現循環依賴,也不允許從低層向高層依賴,以免後續被逼循環依賴。

       這時,需要在註冊中心定義架構體系,列明有哪些層的定義,每個服務暴露或引用時,都必須聲明自己應用屬於哪一層,這樣註冊中心能更快的發現架構的腐化現象。


        服務多了,溝通成本也開始上升,調某個服務失敗該找誰?服務的參數都有什麼約定?

      這時就需要登記每個服務都是誰負責的,並建立一個服務的文檔庫,方便檢索。

 

      慢慢一些敏感數據也都服務化了,安全問題開始變得重要,誰能調該服務?如何授權?

       這樣的服務可能需要一個密碼,訪問時需帶着此密碼,但如果用密碼,要改密碼時,就會很不方便,所有的消費方都要改,所以動態生成令牌(Token)可能會更好,提供方將令牌告之註冊中心,由註冊中心決定是否告之消費方,這樣就能在註冊中心頁面上做複雜的授權模型。


        就算是不敏感的服務,也不是能任意調用,比如某服務突然多了一個消費者,這個消費者的請求量直接把服務給拖跨了,其它消費者跟着一起故障。

      首先服務提供方需要流控,當流程超標時,能拒絕部分請求,進行自我保護。

      其次,消費者上線前和提供者約定《服務質量等級協定(SLA)》,SLA包括消費者承諾每天調用量,請求數據量,提供方承諾響應時間,出錯率等,將SLA記錄在監控中心,定時與監控數據對比,超標則報警。


     雖然有SLA約定,如果不能控制,就只是君子協定,如何確保服務質量?

     比如:一個應用很重要,一個不那麼重要,它們調用同一個服務,這個服務就應該向重要應用傾斜,而不是一視同仁,當支撐不住時,應限制不重要應用的訪問,保障重要應用的可用,如何做到這一點呢。這時,就需要服務路由,控制不同應用訪問不同機器,比如

應用分離:consumer.application = foo => provider.host = 1,2,3consumer.application != foo => provider.host = 5,6讀寫分離:method.name = find*,get* => provider.host = 1,2,3method.name != find*,get* => provider.host = 5,6


  

         服務上線後,需要驗證服務是否可用,但因防火牆的限制,線下是不能訪問線上服務的,不得不先寫好一個測試Main,然後放到線上去執行,非常麻煩,並且容易忘記驗證。

       所以線上需要有一個自動運行的驗證程序,用戶只需在界面上填上要驗證的服務方法,以及參數值和期望的返回值,當有一個服務提供者上線時,將自動運行該用例,並將運行結果發郵件通知負責人。


        服務應用和Web應用是有區別的,它是一個後臺Daemon程序,不需要Tomcat之類的Web容器。但因公司之前以Web應用爲主,規範都是按Web應用的,所以不得不把服務跑在一個根本用不上的Web容器裏,而搭一個這樣的Web工程也非常費事。

       所以需要實現一個非Web的容器,只需簡單的Main加載Spring配置即可,並提供Maven模板工程,只需mvn dubbo:generate 即可創建一個五臟俱全的服務應用。


      開發服務的人越來越多,更注重開發效率,IDE的集成支持必不可少。

通過插件,可以在Eclipse中直接運行服務,提供方可以直接填入測試數據測試服務,消費方可以直接Mock服務不依賴提供方開發。


        因爲暴露服務很簡單,服務的上線越來越隨意,有時候負責服務化的架構師都不知道有人上線了某個服務,使得線上服務魚龍混雜,甚至出現重複的服務,而服務下線比上線還困難。

      需要一個新服務上線審批流程,必須經過服務化的架構師審批過了,纔可以上線。而服務下線時,應先標識爲過時,然後通知調用方儘快修改調用,直到沒有人調此服務,才能下線。


         因服務接口設計的經驗一直在慢慢的積累過程中,很多接口並不能一促而蹴,在修改的過程中,如何保證兼容性,怎麼判斷是否兼容?另外,更深層次的,業務行爲兼容嗎?

       可以根據使用的協議類型,分析接口及領域模型的變更是否兼容,比如:對比加減字段,方法簽名等。

而業務上,可能需要基於自動迴歸測試用例,形成Technology Compatibility Kit (TCK),確保兼容升級。


        隨着服務的不停升級,總有些意想不到的事發生,比如cache寫錯了導致內存溢出,故障不可避免,每次核心服務一掛,影響一大片,人心慌慌,如何控制故障的影響面?服務是否可以功能降級?或者資源劣化?

      應用間聲明依賴強度,哪些功能強依賴,哪些弱依賴,然後基於依賴強度,計算出影響面,並定期測試複查,加強關鍵路徑上的服務的優化和容錯,清理不該在關鍵路徑上的服務。

      提供容錯Mock數據,Mock數據也應可以在註冊中心在運行時動態下發,當某服務不可用時,用Mock數據代替,可以減少故障的發生,比如某驗權服務,當驗權服務全部掛掉後,直接返回false表示沒有權限,並打印Error日誌報警。

       另外,前端的頁面也應採用Portal進行降級,當該Portal獲取不到數據時,直接隱藏,或替換爲其它模塊展示,並提供功能開關,可人工干預是否展示,或限制多少流量可以展示。


        當已有很多小服務,可能就需要組合多個小服務的大服務,爲此,不得不增加一箇中間層,暴露一個新服務,裏面分別調其它小服務,這樣的新服務業務邏輯少,卻帶來很多開發工作量。

       此時,需要一個服務編排引擎,內置簡單的流程引擎,只需用XML或DSL聲明如何聚合服務,註冊中心可以直接下發給消費者執行聚合邏輯,或者部署通用的編排服務器,所有請求有編排服務器轉發。

        並不是所有服務的訪問量都大,很多的服務都只有一丁點訪問量,卻需要部署兩臺提供服務的機器,進行HA互備,如何減少浪費的機器。

        此時可能需要讓服務容器支持在一臺機器上部署多個應用,可以用多JVM隔離,也可以用ClassLoader隔離。


  


      如果你的應用是國際化的,有中文站,美國站之類,因爲時差,美國站的機器晚上閒的時候,可能正是中文站的白天忙時,可以通過資源調度,分時段自動調配和部署雙方應用。



     以上是提給我和大家學習Dubbo同事們的問題,通過Dubbo的使用來深入淺出的領悟吧。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章