服務穩定、高可用

 

服務的穩定性對業務的進行極其重要的;html

若是咱們本身是一個普通用戶,要訪問某個網站,但這個網站一個頁面的打開你要等十來秒甚至幾十秒的時間,請問你還有看下去的慾望嗎? 服務的穩定性及響應速度差會給你的業務帶來如下損失:其一,用戶極可能因這個問題而選擇你的競爭對手;其二,使你的網站或產品的可信度降低;第三,從SEO的角度來看對搜索引擎極度不友好。說一個案例吧,在聚美優品3週年慶搶購活動上,雖然它的前期營銷作得很是好,確實吸引了不少用戶在那一天去訪問他們的網站併產生了大量的訂單,但不幸的是那一天由於他們的服務器不堪重負宕機了,不少用戶還在網上排隊等待。過後用戶掛在嘴邊的就是「仍是淘寶給力,聚美優品就是沒淘寶給力,一個活動網站就塌了」,雖說這不是本質上的問題,但每每用戶會認爲你不及人家,並且是連帶你這個品牌的全部,特別對於一些大品牌。java

因此,咱們服務必須保證服務穩定、高可用。redis

如何作到穩定、高可用呢?算法

 

咱們大部分服務都是以下結構api

 

防範使用方緩存

2.1 服務接口api參數易用性安全

l參數定義:定義具備明確含義的參數名稱,不要出現a、b、x等的參數。服務器

l參數的類型:每個參數有明確的數據類型,不要所有都是String,而儘可能給每個參數定義不一樣合適的數據類型,避免api方法的誤用和減小數據類型的轉換。網絡

l參數的數量:服務接口api中參數個數不宜太多,通常3個左右比較合適,若是個數太多那就建議使用參數類吧多線程

2.2 良好的接口使用說明

l參數有中文:某些狀況下咱們的接口會傳參中文,中文參數就會有編碼要求UTF-8,GBK,若是不約束具體的編碼,可能接口就會有亂碼甚至保存異常。

l無分頁:某些業務邏輯中無分頁,但默認狀況下要返回前N條數據,若是沒有說明就會形成使用方的困惑,徒增溝通時間成本。

l有分頁:定義好默認一頁記錄數,仍是容許使用方自行定義返回記錄數。根據業務場景仍是要約束一頁記錄數,避免數量過大而影響性能。

……

2.3 接口異常處理

        明確、詳細的異常信息在調試api、快速定位解決問題中十分有用,所以咱們必須設計良好的異常信息,以便本身記錄和提供給使用方參考。

l參數檢驗異常

爲了服務接口的安全,咱們都會把參數作校驗及轉換。如參數id是整型類型的 id=81 咱們就會作整型類型的校驗,若是不是整型的就會返回「參數id必須是整型」的提示信息及自定義的錯誤代碼。

l業務邏輯異常

在內部處理業務邏輯時,若是出現異常咱們也要記錄相應的異常信息及自定義的錯誤代碼,而不能只給使用方提示「服務器發生錯誤」這樣信息。估計看到這樣的信息會抓狂,咱們的目的是當使用方拿到錯誤代碼對照接口api使用說明就會很快定位到問題所在。

 

2.4 接口api版本演進或版本控制

隨着業務的發展,老的接口api已不能知足新的業務邏輯,此時是改造老的接口仍是增長新的接口?若是在老的接口中進行改造來支持新的業務邏輯,可是不得不維護老的業務邏輯,無形中增長工做量和難度。實際中咱們能夠新增長接口api,老的api和新的api同時提供服務,而後將老的api平滑過分到新的api。

咱們能夠定義api版本格式以下

/XXX/api/v2/…

 

2.5 接口api業務功能分級與隔離

        對相關的服務或接口區分核心和非核心,並進行隔離部署,避免服務互相影響。

對於服務的依賴區分核心依賴和非核心依賴,在流量突增的狀況下,降級非核心依賴。

優雅降級:對於調用超時的非核心服務,能夠設定一個閾值,若是調用超時的次數超過這個閾值,便自動將該服務降級。此時服務調用者跳過對該服務的調用,並指定一個休眠的時間點,當時間點過了以後,再次對該服務進行重試,若是服務恢復,則取消降級,不然繼續保持該服務的降級狀態。

降級通常就是經過系統中的開關機制實現的。

 

2.6 服務接口api限流

服務接口api的降級和限流都是流量控制的處理策略,同時也是系統的自我保護策略。雖然犧牲了一部分業務功能和高併發量,但換來的系統的可用性。

 

經常使用的限流算法:

l漏桶(Leaky Bucket)算法

l令牌桶算法(Token Bucket)

 

懷疑第三方

 

3.1 設置合理的超時時間

若是超時就應該斷掉請求鏈接,把業務處理的線程讓給別的請求,加快處理同時也減輕了所依賴服務的壓力。

 

3.2 合理的重試機制

        須要結合本身的業務以及異常來仔細斟酌是否使用重試機制。好比調用某第三方服務,報了個異常,有些同窗就無論三七二十一就直接重試,這樣是不對的,好比有些業務返回的異常表示業務邏輯出錯,那麼你怎麼重試結果都是異常;又若有些異常是接口處理超時異常,這個時候就須要結合業務來判斷了,有些時候重試每每會給後方服務形成更大壓力,起到雪上加霜的效果。

 

3.3 異步調用服務接口

咱們的服務接口中都會穿插着業務邏輯,若是使用httpsyncclient異步調用服務接口數據,此時處理本身的業務邏輯再結合異步返回的數據組織最終的業務數據,從而提升了服務接口處理能力。

 

3.4 有兜底,制定好業務降級方案

若是第三方服務掛掉怎麼辦?咱們業務也跟着掛掉?顯然這不是咱們但願看到的結果,若是能制定好降級方案,那將大大提升服務的可靠性。

 l對數據作緩存處理

l友好的錯誤提示

……

 

 

作好本身

 作好本身是個很是大的話題,從需求分析、架構設計 、代碼編寫、測試、code review、上線、線上服務運維等階段均可以重點展開介紹。

此次簡單分享下架構設計、代碼編寫上的幾條經驗原則。

 

4.1 單一職責原則

單一職責原則,在咱們的需求分析、架構設計、編碼等各個階段都很是有指導意義。

  在需求分析階段,單一職責原則能夠界定咱們服務的邊界,服務邊界若是沒界定清楚,各類合理的不合理的需求都接,最後會致使服務出現不可維護、不可擴展、故障不斷的悲哀結局。

  對於架構來說,單一職責也很是重要。好比讀寫模塊放置在一塊兒,致使讀服務抖動很是厲害,若是讀寫分離那將大大提升讀服務的穩定性。

  從代碼角度上講,一個類只幹一件事情,若是你的類幹了多個事情,就要考慮將他分開。這樣作的好處是很是清晰,之後修改起來很是方便,對其它代碼的影響就很小。再細粒度看類裏的方法,一個方法也只幹一個事情,即只有一個功能,若是幹兩件事情,那就把它分開,由於修改一個功能可能會影響到另外一個功能。

 

4.2 控制資源的使用

CPU資源限制

內存資源限制

網絡資源限制

磁盤資源限制

4.2.1 cpu資源限制

a)計算算法優化

  若是服務須要進行大量的計算,好比推薦排序服務,那麼務必對你的計算算法進行優化。

b)鎖

  對於不少服務而言,沒有那麼多耗費計算資源的算法,但cpu使用率也很高,這個時候須要看看鎖的使用狀況,建議是如無必要,儘可能不用顯式使用鎖。

c) 習慣問題

  好比寫循環的時候,千萬要檢查看看是否能正確退出,有些時候一不當心,在某些條件下就成爲死循環,很著名的案例就是《多線程下HashMap的死循環問題》。好比集合遍歷時候使用性能較差的遍歷方式、String +檢查,若是有超過多個String相加,是否使用StringBuffer.append

d)儘可能使用線程池

  經過線程池來限制線程的數目,避免線程過多形成的線程上下文切換的開銷。

e)jvm參數調優

  jvm參數也會影響cpu的使用,如《發佈或重啓線上服務時抖動問題解決方案》。

4.2.2 內存資源限制

a)Jvm參數設置

  經過JVM參數的設置來限制內存使用,jvm參數調優比較靠經驗,能夠參考《Linux與JVM的內存關係分析》。

b)初始化java集合類大小

  使用java集合類的時候儘可能初始化大小,在長鏈接服務等耗費內存資源的服務中這種優化很是重要;

c)使用內存池/對象池

d)使用線程池的時候必定要設置隊列的最大長度

  以前看過好多起故障都是因爲隊列最大長度沒有限制最後致使內存溢出。

e)若是數據較大避免使用本地緩存

  若是數據量較大,能夠考慮放置到分佈式緩存如redis、tair等,否則gc均可能把本身服務卡死;

f)對緩存數據進行壓縮

  好比以前作推薦相關服務時,須要保存用戶偏好數據,若是直接保存可能有12G,後來採用短文本壓縮算法直接壓縮到6G,不過這時必定要考慮好壓縮解壓縮算法的cpu使用率、效率與壓縮率的平衡,一些壓縮率很高可是性能不好的算法,也不適合線上實時調用。

  有些時候直接使用probuf來序列化以後保存,這樣也能節省內存空間。

g)清楚第三方軟件實現細節,精確調優

  在使用第三方軟件時,只有清楚細節後才知道怎麼節約內存。

4.2.3 網絡資源限制

a)減小調用的次數    

  減小調用的次數。常常看到有同窗在循環裏用redis/tair的get,若是意識到這裏面的網絡開銷的話就應該使用批量處理;又如在推薦服務中常常遇到要去多個地方去取數據,通常採用多線程並行去取數據,這個時候不只耗費cpu資源,也耗費網絡資源,一種在實際中經常採用的方法就是先將不少數據離線存儲到一塊 ,這時候線上服務只要一個請求就能將全部數據獲取。

b)減小傳輸的數據量

  一種方法是壓縮後傳輸,還有一種就是按需傳輸,好比常常遇到的getData(int id),若是咱們返回該id對應的Data全部信息,一來人家不須要,二來數據量傳輸太大,這個時候能夠改成getData(int id, List<String> fields),使用方傳輸相應的字段過來,服務端只返回使用方須要的字段便可。

 

4.2.4 磁盤資源限制

打日誌要控制量,並按期清理。1)只打印關鍵的異常日誌;2)對日誌大小進行監控報警。3)按期對日誌進行清理,好比用crontab,每隔幾天對日誌進行清理;4)打印日誌到遠端,對於一些比較重要的日誌能夠直接將日誌打印到遠端HDFS文件系統裏。

相關文章
相關標籤/搜索