HTTP(S) 负载平衡问题排查

本指南介绍如何排查 Google Cloud 外部 HTTP(S) 负载平衡器的配置问题。

概览

本指南中讨论的问题类型包括:

  • 常规连接问题
  • 排查后端 HTTP/2 问题
  • 自定义源站和互联网 NEG 问题
  • 无服务器 NEG 问题(Beta 版)

准备工作

在调查问题之前,请先熟悉以下页面。

关于常规连接:

关于自定义来源和互联网 NEG:

对于无服务器 NEG:

排查常规连接问题

原因不明的 502 错误

在完成负载平衡器配置后,如果 502 错误的持续时间超过几分钟,则可能是因为以下原因之一:

如需验证运行状况检查流量是否已到达后端虚拟机,请启用运行状况检查日志记录并搜索成功的日志条目。

经过负载平衡处理的流量不含原始客户端的源地址

对于从负载平衡器到您实例的流量,其 IP 地址范围为 130.211.0.0/2235.191.0.0/16。查看负载平衡实例上的日志时,您无法看到原始客户端的源地址。相反,您会看到此范围的源地址。

在 Cloud Storage 存储分区上尝试查看对象时得到权限错误

为了通过负载平衡来传送对象,Cloud Storage 对象必须可公共访问。确保更新正在传送的对象的权限,使其公开可读

网址无法传送预期的 Cloud Storage 对象

需要传送的 Cloud Storage 对象基于您的网址映射和您请求的网址来确定。若请求路径映射到您网址映射中的后端存储分区,Cloud Storage 对象通过将完整请求路径附加到网址映射指定的 Cloud Storage 存储分区上来确定。

例如,如果您将 /static/* 映射到 gs://[EXAMPLE_BUCKET],则向 https://<GCLB IP or Host>/static/path/to/content.jpg 发出的请求将尝试传送 gs://[EXAMPLE_BUCKET]/static/path/to/content.jpg。如果该对象不存在,您将获得以下错误消息而非该对象:


NoSuchKey
The specified key does not exist.

未执行压缩

HTTP(S) 负载平衡本身不会对响应进行压缩或解压缩,但它可以提供由后端服务生成的响应,这些响应会使用 gzipDEFLATE 等工具进行压缩。

如果由 HTTP(S) 负载平衡提供的响应未被压缩,但本应进行压缩,请仔细检查以确保您实例上运行的 Web 服务器软件已配置为压缩响应。默认情况下,某些 Web 服务器软件会对包含 Via 标头的请求自动停用压缩功能,该标头表示请求由代理转发。HTTP(S) 负载平衡代理会依据 HTTP 规范的要求为每个请求添加一个 Via 标头。如需启用压缩功能,您可能必须覆盖 Web 服务器的默认配置,以指示其对响应进行压缩(即便是请求中包含了 Via 标头)。

如果您使用的是 nginx Web 服务器软件,请修改 nginx.conf 配置文件以启用压缩功能。此文件的位置取决于 nginx 的安装位置。在大部分 Linux 发行版中,此文件的存储位置都是 /etc/nginx/nginx.conf。如需将 nginx 压缩功能与 HTTP(S) 负载平衡搭配使用,请将以下两行代码添加到 nginx.conf 的 http 部分中:

gzip_proxied any;
gzip_vary on;

即使对于代理(如 HTTP(S) 负载平衡)转发的请求,第一行也可以进行压缩。第二行代码用于将 Vary: Accept-Encoding 标头添加到响应。Vary: Accept-Encoding 用于向缓存代理(例如 Cloud CDN)发送通知,告知它们应为可压缩资源的已压缩和未压缩变体保留单独的缓存条目。

修改 nginx.conf 之后,您必须重启 nginx,这样新配置才能生效。在大部分 Linux 发行版中,您可以通过运行 sudo service nginx restart/etc/init.d/nginx restart 来重启 nginx。

解决 HTTP 408 错误

借助 HTTP 流量,客户端完成发送其请求的最长时间等于后端服务超时值。如果看到带有 jsonPayload.statusDetail client_timed_out 的 HTTP 408 响应,则表示客户端的请求被代理或者后端的响应被代理时跟不上进度。如果问题是由于客户端遇到性能问题,您可以通过增加后端服务超时值来解决此问题。

排查后端 HTTP/2 问题

字段 resource.loadBalancingScheme 的下列值无效:'EXTERNAL'

目前尚不支持基于后端服务的网络负载平衡。

如果您在创建后端服务时未选择“全球”选项,可能会发生这种情况。当您按如下方式发出 gcloud 命令时,系统会提示您指定地区或将负载平衡器指定为全球负载平衡器:

gcloud beta compute backend-services create service-test \
    --health-checks=hc-test \
    --project=test1 \
    --protocol=http2

对于以下后端服务,系统会显示以下提示:

- [service-test] choose a region or global:
[1] global
[2] region: [REGION_A_NAME]
[3] region: [REGION_B_NAME]
....
Please enter your numeric choice:

对于 HTTP(S) 负载平衡器,后端服务必须是全球的,因此您必须选择选项 1 或发出带有 --global 选项的 gcloud 命令:

gcloud beta compute backend-services create service-test \
    --health-checks=hc-test \
    --project=test \
    --protocol=http2 \
    --global

原因不明的 502 错误

请确保您的后端实例运行状况良好且支持 HTTP/2 协议。您可以通过使用 HTTP/2 测试与后端实例的连接来验证这一点。确保该虚拟机使用符合 HTTP/2 规范的加密套件。例如,某些 TLS 1.2 加密套件不受 HTTP/2 支持。请参阅 TLS 1.2 加密套件黑名单

验证该虚拟机使用 HTTP/2 协议后,请确保您的防火墙设置允许运行状况检查程序和负载平衡器进行直通访问。

如果防火墙设置没有问题,请确保负载平衡器已配置为与该虚拟机上的正确端口通信。

排查自定义源站和互联网 NEG 问题

流量未到达端点

配置服务后,在以下情况下,可通过外部 HTTP(S) 负载平衡器访问新端点:

  • 端点已关联到互联网 NEG。
  • 相关联的 FQDN 可以得到成功 DNS 解析(如果您使用的是 FQDN 端点类型)。
  • 端点可通过互联网访问。

如果流量无法到达端点,从而导致出现 HTTP(s) 的 502 错误代码,请检查以下内容:

  • 使用 dig 或 nslookup 这类工具来查询 _cloud-eoips.googleusercontent.com DNS TXT 记录。请记下(ip4: 后面的)CIDR 并确保您的防火墙或云端访问控制列表 (ACL) 允许使用这些范围。

配置自定义源站后,发送到自定义源站的请求失败,并显示 5xx 错误

  • 检查日志记录
  • 验证网络端点组为自定义源站配置了正确的 IP:Port 或 FQDN:Port。
  • 如果您使用的是 FQDN,请确保它可以通过 Google 公共 DNS 进行解析。您可以使用上述步骤直接使用网页界面验证 FQDN 是否可通过 Google 公共 DNS 进行解析。
  • 如果您目前仅通过外部 IP 访问 HTTP(S) 负载平衡器,且您的源 Web 服务器需要主机名,请确保您已通过配置自定义请求标头向后端发送了有效的 HTTP 主机标头。
  • 如果通过 HTTPS 或 HTTP2(在后端服务的 protocol 字段中设置)与后端进行的通信配置为 INTERNET_FQDN_PORT 自定义源站端点,请确保您的源站展示有效的 TLS (SSL) 证书,同时配置的 FQDN 与证书的 SAN 列表中的 SAN(主题备用名称)匹配。有效证书指由公共证书授权机构签发且未过期的证书。
  • 使用 INTERNET_FQDN_PORT 自定义源站端点时,HTTPS 负载平衡器不接受自签名证书,并且会拒绝此类证书。
  • 如果将 HTTPS 或 HTTP/2 与 INTERNET_IP_PORT 类型的端点结合使用,则系统不会执行 SSL 证书验证/SAN 检查。这意味着可以使用自签名证书。使用 SSL 时,我们建议使用 INTERNET_FQDN_PORT 端点来确保服务器证书和 SAN 得到验证。

来自我的自定义源站的响应不被 Cloud CDN 缓存

确保:

  • 通过将 enableCDN 设为 true,您已在包含指向自定义源站的 NEG 的后端服务上启用 Cloud CDN。
  • 您的自定义源站提供的响应符合 Cloud CDN 缓存要求。例如,您从源站发送 Cache-Control: public, max-age=3600 响应标头。

排查无服务器 NEG 问题

请求失败并显示 404 错误

确保底层无服务器资源(例如 App Engine、Cloud Functions 或 Cloud Run(全代管式)服务)仍在运行。如果无服务器资源已删除,但无服务器 NEG 仍然存在,则外部 HTTP(S) 负载平衡器会继续尝试将请求路由至不存在的服务。这会导致出现 404 响应。

通常,外部 HTTP(S) 负载平衡器无法检测底层无服务器资源是否按预期工作。这意味着如果一个地区中的服务返回错误,但该地区中的整体 Cloud Run(全代管式)、Cloud Functions 或 App Engine 基础架构正常运行,则外部 HTTP(S) 负载平衡器不会自动将流量定向到其他地区。将用户流量路由到服务的新版本之前,请务必对新版本进行全面测试。

处理网址掩码不匹配问题

如果将已配置的网址掩码应用于用户请求网址,但没有生成服务名称,或者导致生成不存在的服务名称,则负载平衡器可能会根据使用的无服务器计算平台,对这些不匹配问题进行不同的处理。

Cloud Run(全代管式):如果网址掩码不匹配,则负载平衡器将返回 HTTP 错误 404 (Not Found)。

Cloud Functions:如果网址掩码不匹配,则负载平衡器将返回 HTTP 错误 404 (Not Found)。

App Engine:如果网址掩码不匹配,则 App Engine 会使用 dispatch.yaml 和 App Engine 的默认路由逻辑来确定将请求发送到哪个服务。