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秒多,也许正是由于长时间的等待致使用户中止了下载任务。

原文连接

相关文章
相关标签/搜索