系統負載篇:api
一,什麼是Load Average?服務器
系統負載(System Load)是系統CPU繁忙程度的度量,即有多少進程在等待被CPU調度(進程等待隊列的長度)。
平均負載(Load Average)是一段時間內系統的平均負載,這個一段時間通常取1分鐘、5分鐘、15分鐘。網絡
二,如何查看Load?併發
1, cat /proc/loadavgsocket
2, uptimetcp
3, top高併發
以上三種方式均可以查看當前系統的負載,而load average: 0.95, 0.94, 0.92 後邊這三個數字是最回味無窮的優化
他們按照前後順序依次表徵一分鐘,五分鐘,十五分鐘的系統平均負載(其實就是這三個時間段真正在忙碌的進程即CPU有多少個)ui
三, 如何評估當前系統的平均負載水平?url
分割的界限:通常有經驗的系統管理員會將負載飽滿這條標準定在70%。(即忙碌的CPU佔服務器總核數的百分比)
當前,咱們線上服務器通通採用的是64核(vcpu)的ECS,而xadserver經過uwsgi起服務時,指定的進程數爲45,讓咱們來換算一下比例:45 / 64 = 0.703125
因此咱們當前起服務的進程數剛恰好是略超70%標準線
咱們再去線上讀一下負載水平:
1,5,15三個時段的活躍CPU大概爲45,與進程數相同,因此咱們服務器的負載由於咱們的進程數會保持在70%左右(服務正常的前提下)
圖中負載較低的時段爲每日請求數較少的時段,由圖線趨勢可知,每日晚9點至第二天凌晨5點請求數持續下降,以後再持續升高,最高系統負載由服務的45個線程決定系統負載
上圖爲事故當天系統負載的曲線變化
11點開始併發較高,而當時因爲重啓服務的緣由,slb將併發壓力分攤到其他5臺機器上,致使其他5臺機器系統負載升高(但並無超出64核的限制,因此負載升高只是服務被擊穿的表象,並非根本緣由,但能夠做爲佐證的一個參考依據)
服務被擊穿後,系統負載的變化曲線忽高忽低,暫無肯定結果,私覺得服務被擊穿後,實時處理的客戶端請求急劇下降,沒法正常返回,故曲線驟降,而負載降至冰點後,大量客戶端重試請求和正常請求涌入,再次擊穿服務,如此往復致使曲線驟降驟升
TCP篇:
在Linux平臺上,不管編寫客戶端程序仍是服務端程序,在進行高併發TCP鏈接處理時,最高的併發數量都要受到系統對用戶單一進程同時可打開文件數量的限制(這是由於系統爲每一個TCP鏈接都要建立一個socket句柄,每一個socket句柄同時也是一個文件句柄)。
對於文件句柄的數量有三層限制
1,軟限制:Linux在當前系統可以承受的範圍內進一步限制用戶同時打開的文件數
2,硬限制:根據系統硬件資源情況(主要是系統內存)計算出來的系統最多可同時打開的文件數量(一般軟限制小於或等於硬限制。)
3,系統限制:當前Linux系統最多容許同時打開(即包含全部用戶打開文件數總和)文件個數,是Linux系統級硬限制,全部用戶級的打開文件數限制都不該超過這個數值。一般這個系統級硬限制是Linux系統在啓動時根據系統硬件資源情況計算出來的最佳的最大同時打開文件數限制,若是沒有特殊須要,不該該修改此限制,除非想爲用戶級打開文件數限制設置超過此限制的值
軟硬限制:/etc/security/limits.conf -→ 文件中的soft nofile/hard nofile
系統限制:cat /proc/sys/fs/file-max
當前這三個限制在咱們線上機器設置的數量均爲 655350
因此咱們線上單臺服務器理論上最高併發支持 655350(實例支持的真實最大併發與服務器的硬件配置和網絡環境有關)
事故當天單臺ECS實例的TCP鏈接中 ESTABLISHED 數量在24000 - 25000之間,總的TCP鏈接數數量保持在 90000 - 100000之間,總TCP鏈接數-ESTABLISHED鏈接數=TIME_WAIT鏈接數 + CLOSE_WAIT鏈接數(其餘類型的TCP狀態影響較小,暫不考慮)
處於TIME_WAIT和CLOSE_WAIT狀態的TCP鏈接會佔用當前系統的文件句柄,影響系統的併發處理能力,而當前線上服務器對於TIME_WAIT處理的系統配置文件已是優化過的,因此該事故的直接緣由是TCP鏈接數超過了系統實際可承載的最大鏈接數
在服務正常運轉時,單臺服務器的 ESTABLISHEED鏈接數爲9000-10000,總的TCP鏈接數數量保持在45000 - 60000之間
綜上計算當前slb併發:9500 * 10 = 95000
查詢slb併發鏈接數,當前slb的活躍鏈接數與每臺ECS實例的ESTABLISHED狀態TCP鏈接數總和數量級相同
監控篇:
系統負載只是線上服務出了問題以後的一種現象,而要作到提早發現就是監控ECS實例的TCP鏈接狀況,對於不健康的TIME_WAIT以及CLOSE_WAIT提早發現(其實最終仍是監控當前系統的TCP總鏈接數)
監控命令:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
上邊是一臺線上機器的TCP鏈接狀況,能夠看到ESTABLISHED狀態的鏈接數目前爲9000數量級,而TIME_WAIT高達40000,這是一種正常狀況
由於咱們的服務屬於 高併發短鏈接,當服務器處理完請求後會馬上主動正常關閉鏈接,這個場景就會出現大量socket處於TIME_WAIT狀態,而咱們線上服務器已經針對此業務場景優化過系統配置
而最終形成TCP鏈接過多打掛服務的直接緣由就是總的TCP鏈接數佔據過多文件句柄,超出系統承受範圍。
因此預防線上ECS沒法承受預期以外的高併發,就須要提早監控ECS的當前TCP總鏈接數,設置閾值,提早報警。