SLB訪問日誌分析:基於客戶端來源和HTTP狀態碼的實踐

摘要: 阿里雲負載均衡SLB能夠對多臺雲服務器(ECS)進行流量分發,支持TCP的四層負載均衡和基於HTTP/HTTPS的七層負載均衡。使用SLB能夠下降單臺ECS異常時對業務的衝擊,提高系統可用性。同時,結合彈性伸縮服務(ESS)動態擴容、縮容後端服務器能夠快速應對業務流量的變化。算法

阿里雲負載均衡SLB能夠對多臺雲服務器(ECS)進行流量分發,支持TCP的四層負載均衡和基於HTTP/HTTPS的七層負載均衡。使用SLB能夠下降單臺ECS異常時對業務的衝擊,提高系統可用性。同時,結合彈性伸縮服務(ESS)動態擴容、縮容後端服務器能夠快速應對業務流量的變化。後端

SLB七層訪問日誌內容豐富,提供近30個字段,例如:收到請求的時間、客戶端的IP地址、處理Latency、請求URI、後端RealServer(阿里雲ECS)地址、返回狀態碼等。在您開啓SLB七層訪問日誌功能後,SLB會記錄對應實例上全部訪問日誌到日誌服務。本文以兩個主題向你們介紹如何經過日誌服務來發掘SLB訪問日誌背後蘊含的一些價值。服務器

請求從哪裏來
這是一個關於client_ip的問題,直接看訪問日誌的client_ip字段就能夠回答。但有時會發現client_ip老是那麼幾個值,直覺告訴咱們不大對勁:網絡

圖片描述

一個客戶端的請求從最初的ip到SLB負載均衡,若是不通過代理,那麼client_ip記錄的就是原始客戶端ip。而假如請求通過proxy屢次轉發,這種狀況下訪問日誌記錄的client_ip就不能真實反應請求來源了。負載均衡

好在SLB訪問日誌中有另兩個字段能夠幫助咱們解決真實client_ip問題:函數

http_x_forwarded_for,取自HTTP擴展頭X-Forwarded-For字段,是RFC7293標準。假設客戶端在client_0發出請求,到達服務端以前依次通過了三個代理proxy_一、proxy_二、proxy_3,其中proxy_3直連負載均衡器,那麼proxy_3會在X-Forwarded-For上追加proxy_2的ip表示是在替proxy_2轉發請求。這樣多層級聯後造成一個用逗號鏈接的字符串"client_0_ip,proxy_1_ip,proxy_2_ip",字符串中的第一個便是原客戶端ip。
http_x_real_ip,取自HTTP自定義頭X-Real-IP字段,非正式標準但在業內廣泛使用。在各層代理始終堅持記錄原始客戶端ip的前提下,這是最方便且正確的取值。
值得注意的是,X-Forwarded-For和X-Real-IP字段都有可能出現不許確的狀況,感興趣的同窗能夠讀一下這篇文章:HTTP請求頭中的X-Forwarded-For。優化

本文按照X-Real-IP優先策略計算真實的請求來源ip,算法用以下決策樹來表達:阿里雲

圖片描述

當http_x_forwarded_for、http_x_real_ip字段取值爲字符串"-"時,表示該字段值不是有效內容。那麼經過SQL的case/when語法把上圖的計算方法翻譯以下:spa

select (case
        when http_x_real_ip = '-' then (case
                                        when http_x_forwarded_for = '-' then client_ip
                                        when split_part(http_x_forwarded_for, ',', 1)  = '-' then client_ip
                                        else split_part(http_x_forwarded_for, ',', 1) 
                                        end)
        else http_x_real_ip
        end) as real_client_ip
real_client_ip是經過算法獲得的優化版真實客戶端ip:

圖片描述

在real_client_ip基礎上,可使用日誌服務IP地理函數計算訪問來源的地理(國家、省市、運營商、經緯度)信息。例如按照省維度統計PV分佈:翻譯

圖片描述

HTTP狀態碼說明了什麼
408 Request Timeout
現象
客戶端請求部署在SLB上的服務,但常常出現網絡超時狀況。

排查過程
首先用SQL統計是否有異常的狀態碼:

not (status : 200) | select status, count(*) as pv group by status order by pv desc

分析發如今最近15分鐘的訪問日誌中有些408返回的請求:

圖片描述

關於408狀態碼,它表示服務端在必定時間內沒有收到完整的請求,這個時候服務端決定再也不等待,在響應中將Connection首部值設置爲close並主動關閉鏈接。

發生408錯誤的時候,表現爲Request Timeout。最大可能的兩個緣由有:客戶端沒有在超時時間內把數據包發到服務端;或者是由於服務端負載很重,沒有及時處理請求。若是經過監控能夠排除服務端負載緣由,那麼能夠將更多關注點轉移到客戶端身上。

統計408狀態的client_ip來源:

status : 408 | select client_ip, count(*) as pv group by client_ip order by pv desc

若是client_ip集中在幾個特定來源上,那麼,個別客戶端網絡流量致使問題的可能性就比較大。

同時,查看408狀態碼的日誌發現,異常請求的upstream_addr、upstream_status都沒有記錄,這說明請求沒有到達後端real server。這個時候能夠認爲,客戶端問題致使網絡超時的可能性是很大了。

圖片描述

接下來,就請到客戶端上查看網路監控或抓包調查吧。

499 Client Closed Request
現象
SLB負載均衡上的流量出現下跌,同時後端服務器上沒有看到5xx錯誤。

排查過程
經典開局,先看異常狀態碼分佈,但此次咱們懷疑是499致使的:

圖片描述

499狀態碼錶示服務端Nginx正在處理請求過程當中,客戶端主動關閉了鏈接。

經過異常的訪問日誌加以印證,upstream_addr記錄了請求在real server上進行處理,可是沒有記錄響應的後端狀態碼upstream_status,說明後端服務器沒有完成請求的處理。而且,整個請求的處理時間request_time用了10秒多,也許正是由於長時間的等待致使用戶中止了下載任務。

原文連接

相關文章
相關標籤/搜索