如何排查 Application Load Balancer 会话粘性问题?

上次更新时间:2022 年 5 月 2 日

我的 Application Load Balancer 使用基于持续时间的粘性基于应用程序的粘性会话。该负载均衡器已配置为将所有用户会话请求路由至相同目标。但是,用户会话请求却路由到了不同目标。

简短描述

粘性会话使用 cookie 帮助客户端在 cookie 的生命周期内保持与同一实例的连接。使用粘性会话会将负载均衡器配置为将用户会话绑定至特定实例。这意味着在会话过程中来自用户的所有请求都会发送到相同实例。随着时间的推,此连接假设可能会导致不平衡。

如果出现以下情况,粘性会话可能会失败:

  • 注册的目标没有生成 cookie
  • 客户端没有在请求标头中返回 cookie
  • cookie 的格式不正确
  • 基于持续时间的会话已过
  • 会话请求正在通过多个负载均衡器
  • 目标运行状况状态已更改为不正常
  • AWS 服务已禁用粘性

注意:在开始之前,请确保您已查阅 Application Load Balancer 的粘性会话中的要求注意事项部分。

解决方法

基于应用程序的会话粘性

1.    检查负载均衡器中是否存在 HTTP 错误。有关说明,请参阅排查 Application Load Balancer 问题

2.    要检查放置在后端实例或负载均衡器上的 cookie,请运行类似于以下内容的 curl 命令:

注意:将 DNS 名称替换为您的负载均衡器名称。

[ec2-user@ip-172-31-22-85 ~]$ curl -vko /dev/null internal-EXAMPLE-ELB-1430759361.eu-central-1.elb.amazonaws.com

注意:Linux curl 实用程序也可以安装在 Windows 操作系统上。

示例输出:

...

< Set-Cookie: PHPSESSID=k0qu6t4e35i4lgmsk78mj9k4a4; path=/

< Set-Cookie:

AWSALBAPP-0=438DC7A50C516D797550CF7DE2A7DBA19D6816D5E6FB20329CD6AEF2B40030B12FF2839757A60E2330136A2182D27D049FB9D887FBFE9E80FB0724130FB3A86A4B0BAC296FDEB9E943EC9272FF52F5A8AEF373DF33;PATH=/

...

3.    要验证注册的目标是否生成了应用程序 cookie,请向实例 IP 地址发送 HTTP 请求,如下所示:

[ec2-user@ip-172-31-22-85 ~]$ curl -vko /dev/null 172.31.30.168

示例输出:

...

< Set-Cookie: PHPSESSID=5pq74110nuir60kpapj04mglg4; path=/

...

4.    验证注册的目标生成的 cookie 名称是否与步骤 2 和步骤 3 中负载均衡器上的 cookie 名称相同。

5.    如果目标生成了应用程序 cookie,而负载均衡器生成的是 AWSALBAPP cookie,请确保客户端在后续请求中同时发送这两个 cookie。如果客户端无法包括应用程序或 AWSALB cookie,则粘性无效。要验证客户端是否同时发送应用程序和 AWSALBAPP cookie,请在客户端上捕获数据包。使用 tcpdumpWireshark 实用程序进行分析,或使用浏览器网络调试工具检索请求标头中的 cookie 信息。

6.    检查负载均衡器将请求路由到哪个后端实例。您可以通过运行类似于以下内容的脚本显示使用实例元数据的实例 ID:

<?php $instance_id =file_get_contents('http://169.254.169.254/latest/meta-data/instance-id');
echo "instance id = " . $instance_id . "\\xA";
?>

7.    查看 Elastic Load Balancing 访问日志,以检查来自同一用户的请求是否路由到不同的注册目标。有关说明,请参阅 Application Load Balancer 的访问日志

8.    验证已启用粘性的目标组下的所有目标的运行状况是否正常。如果目标运行状况更改为“不正常”,则粘性中断,且负载均衡器会停止将请求路由到该目标。然后,负载均衡器会自动选择一个新的运行状况正常的目标并建立粘性会话。即使运行状况为“不正常”,负载均衡器仍会继续将请求路由到新目标。有关运行状况检查的更多信息,请参阅目标组的运行状况检查

9.    检查您的负载均衡器中是否存在任何可能已禁用粘性的 AWS 服务,例如 Amazon Elastic Kubernetes Service (Amazon EKS)。检查具有 API 名称 “ModifyTargetGroupAttributes” 和属性“stickiness.enabled” 的查看 CloudTrail 事件

基于持续时间的会话粘性

1.    运行与以下包含负载均衡器 DNS 名称类似的命令,以检查响应中是否有 AWSALB cookie:

[ec2-user@ip-172-31-22-85 ~]$ curl -vko /dev/null internal-TESTELB-1430759361.eu-central-1.elb.amazonaws.com

示例输出:

...< Set-Cookie: 
AWSALB=438DC7A50C516D797550CF7DE2A7DBA19D6816D5E6FB20329CD6AEF2B40030B12FF2839757A60E2330136A2182D27D049FB9D887FBFE9E80FB0724130FB3A86A4B0BAC296FDEB9E943EC9272FF52F5A8AEF373DF33;PATH=/
...

注意:如果响应中没有 AWSALB cookie,则客户端和后端实例之间没有粘性。

2.    如果负载均衡器生成了 AWSALB cookie,请确保客户端在后续请求中发送此 cookie。如果客户端无法包括 AWSALB Cookie,则粘性无效。要验证客户端是否发送了 AWSALB cookie,请在客户端上捕获数据包。使用 tcpdumpWireshark 实用程序进行分析,或使用浏览器网络调试工具检索请求标头中的 cookie 信息。

3.    检查负载均衡器上配置的持续时间。如果 cookie 有效期已过,则在负载均衡器发出新的 cookie 之前,客户端会话将不再停留在注册实例上。

4.    如果请求通过多个负载均衡器,请验证粘性是否仅在一个负载均衡器上启用。如果多个负载均衡器生成了 cookie,则该负载均衡器将替换原始 cookie,并且粘性失效。

对于 Classic Load Balancer,请参阅如何排查 Classic Load Balancer 会话粘性问题?