使用负载均衡SLB后出现500、502和504状态码

问题描述

配置负载均衡SLB之后,访问网站出现“500 Internal Server Error”、“502 Bad Gateway”和“504 Gateway Timeout”等错误时,可能由多种原因导致,例如运营商拦截、客户端异常行为导致云盾封堵、负载均衡配置错误、健康检查失败或者后端ECS实例Web应用访问问题。本文列举了此类问题的对应问题原因的解决方法,若没有解决问题,可以参见排查步骤定位并解决问题。

问题原因

本问列举此类问题原因如下所示。

解决方案

对应问题原因的解决方法

源站域名没有备案或者域名没有在高防中配置七层转发规则

如果源站域名没有备案,请将源站域名备案,详情请参见备案。如果域名配置了高防,请配置对应的域名规则,详情请参见规则

客户端IP地址被云盾拦截

将客户端IP地址添加至IP白名单,请参见IP白名单,排除云盾的影响。

客户端IP地址被运营商拦截

测试其他ISP运营商的客户端是否有此问题,如果仅仅是某个固定运营商网络的客户端访问有问题,一般是该运营商拦截导致。可以抓包查看是否被运营商拦截或提交工单联系阿里云技术支持排查。如果被运营商拦截,则需要联系运营商解决该问题。

后端ECS安全防护软件拦截

100.64.0.0/10(100.64.0.0/10是阿里云保留地址,其他用户无法分配到该网段内,不会存在安全风险)是负载均衡服务器IP段,主要用于健康检查和转发请求。如果安装安全软件或者开启系统内部防火墙,可以将此IP地址段加入白名单,或者卸载此类软件,避免出现500或502状态码。本小节以Linux系统的Iptables为例进行演示。

  1. 登录问题后端服务器,执行以下命令,查看filter表的所有规则。

    iptables -nL

    系统显示类似如下,说明后端服务器禁止负载均衡SLB内网地址段请求。

    image
  2. 可以参考以下命令,删除此规则。

    说明

    如果Iptables可以关闭,执行/etc/init.d/iptables stop命令关闭即可。

    sudo iptables -t filter -D INPUT -s 100.64.0.0/10 -j DROP
  3. 执行以下命令,确认没有禁止负载均衡SLB内网地址段请求。

    sudo iptables -nL

后端ECS实例Linux内核参数配置错误

当后端ECS实例为Linux系统时,负载匀衡SLB由HTTP协议改成TCP协议时,需要注意关闭系统内核参数中rp_filter相关设置。将/etc/sysctl.conf系统配置文件的以下三个参数的值设置为0,然后执行sysctl -p命令即可。

net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.eth0.rp_filter = 0

后端ECS实例性能瓶颈

检查后端ECS的CPU和外网带宽等参数,这些性能参数都可能导致访问异常。如果是ECS实例整体系统性能不足,可以通过扩容后端ECS实例消除此问题。

健康检查失败导致负载均衡出现502状态码

当出现健康检查失败时,请参见健康检查异常排查。此外,若未开启负载均衡SLB的健康检查,同时服务器中Web服务无法正常处理HTTP请求,比如Web服务未运行,也会出现502状态码。

健康检查正常但Web应用报502状态码

502状态码错误提示表明负载均衡可以将来自客户端的请求转发到后端服务器,但是由于服务器中Web应用处理异常,导致出现该提示,所以排错的方向是针对服务器中Web应用的配置以及运行情况进行分析。例如Web应用处理HTTP请求的时间超过了负载均衡的超时时间。

在七层(HTTP/HTTPS)监听配置中,连接请求超时时间默认值为60秒,若后端ECS实例对PHP请求的处理时间超过60秒,此时负载均衡SLB会返回504状态码。对于四层(TCP/UDP)监听来说,由于连接请求超时时间默认值为900秒,相对来说不容易出现后端ECS实例对PHP请求的处理时间超过900秒的情况。

确认Web服务及其依赖服务正常运行,检查PHP请求处理情况,优化后端PHP请求处理。以Nginx和PHP-FPM为例进行分析说明。

  • 处理PHP请求的进程数达到上限。

    当前服务器中的PHP请求总数已经达到了PHP-FPM中max_children设置的上限,如果后续有新的PHP请求到达服务器,通常负载均衡SLB会随机返回502或504状态码。

    • 如果已有的PHP请求被处理完成,新请求被继续处理,则一切正常。

    • 如果已有的PHP请求处理较慢,新的PHP请求处于等待状态,直至超过Nginx的fastcgi_read_timeout值,则会出现504状态码。

    • 如果已有的PHP请求处理较慢,新的PHP请求处于等待状态,直至超过Nginx的request_terminate_timeout值,则会出现502状态码。

  • PHP脚本执行时间超时,即如果PHP-FPM处理PHP脚本的时长超过了Nginx中request_terminate_timeout设置的值,则会出现502状态码,同时在Nginx日志中可以查看到类似以下错误记录。

    [error] 1760#0: *251777 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: XXX.XXX.XXX.XXX, server: localhost, request: “GET /timeoutmore.php HTTP/1.1”, upstream: “fastcgi://127.0.0.1:9000”
  • 健康检查针对的是静态页面,因此当健康检查正常时,由于实际处理动态请求的进程异常,例如PHP-FPM未启动运行,则会导致返回报错。

业务访问逻辑问题

请确认负载均衡SLB四层监听的后端ECS实例,在业务层面不存在通过SLB实例IP地址访问SLB实例的情况。因为在该情况下,后端实例通过负载均衡地址访问自身所监控的端口后,根据负载均衡调度策略的不同,可能会将相应的请求调度到自身实例上。导致出现自己访问自己的情况,造成死循环,进而导致出现500或502状态码。

排查步骤

若以上内容没有解决问题,可以参考以下排查步骤定位并解决问题。

  • 请确认是所有客户端访问出现问题,还是部分客户端有问题。如果仅是部分客户端问题,排查该客户端是否被云盾阻挡,负载均衡域名或者IP是否被ISP运营商拦截。

  • 查看500、502和504状态码页面,判断是负载均衡问题、高防配置问题还是后端ECS配置问题。

    • 高防配置问题:如果配置了高防,请确认高防的七层转发配置正确。

    • 负载均衡问题:

      • 检查负载均衡状态,查看是否存在健康检查失败的情况,如果有健康检查失败的情况,请参见健康检查失败

      • 尝试将七层监听切换为四层监听,查看问题是否会复现。

    • 后端ECS配置问题:如果5XX状态码间断发生,很可能是后端某一台ECS实例的配置问题。在客户端的hosts文件中,将域名解析至后端ECS的IP地址上进行访问,检查是否是后端ECS问题。

      • 如果确认是后端ECS问题,请检查后端ECS实例的Web应用日志是否有相关错误,Web服务是否正常运行,确认Web访问逻辑是否有问题,卸载服务器上杀毒软件重启测试。

      • 检查后端ECS实例是否存在CPU、内存、磁盘或网络等性能瓶颈。

      • 如果ECS实例是Linux操作系统,检查后端ECS实例TCP内核参数配置是否正确。

具体的排查思路以下图所示。

适用于

负载均衡SLB。