每个 AZ 中没有 Target 的 AWS 网络负载均衡器
AWS Network Load Balancer without Target in every AZ
在 AWS 网络负载均衡器文档中,它说当为目标组指定实例时,它必须在负载均衡器注册的每个 AZ 中包含一个实例。这不是强制执行的。
如果您在 3 个 AZ 中注册了一个 NLB,但在 AZ1 中只有一个目标 EC2 实例,流量会怎样?如果您启用跨 AZ 负载平衡,会有什么不同吗?
What happens to traffic if you have an NLB registered in 3 AZs, but only a single target EC2 instance in AZ1? What if you enable cross AZ load balancing, does that make any difference?
在此特定场景中(NLB 在 3 个可用区中,单个实例在 1 个可用区中),什么都没有发生。从 end-user 的角度来看,有或没有 cross-zone 负载平衡没有明显的区别。在任何一种情况下都可以访问该实例。
为了验证这一点,我开发了一个简单的 CloudFormation 模板,它创建了 NLB,有或没有 cross-zone 负载平衡,以及 1 个实例。该模板允许使用不同的 NLB、cross-zone 和实例位置进行 简单实验 。我在 us-east-1
区域和默认 VPC 中使用了模板。
您为模板指定了几个参数,包括:
NLBSubnetsIds - 启用 NLB 的子网。您必须先在控制台中检查,哪些子网在哪些可用区中。
InstanceSubnetId - 实例的子网。如果您想使用实例位置,您可以再次检查哪个子网在哪个 AZ 中。您必须确保在为您的 NLB 设置的可用区之一中创建该实例。
CrossZoneEnabled - 为 NLB 启用或禁用 [=65=] 平衡。
从模板创建堆栈并通过实例健康检查(可能需要 1 或 2 分钟)后,您可以在浏览器中访问 NLB DNS 以查看托管的示例网页 在实例上。
---
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
NLBSubnetsIds:
Type: List<AWS::EC2::Subnet::Id>
InstanceSubnetId:
Type: AWS::EC2::Subnet::Id
AmazonLinux2AMIId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
CrossZoneEnabled:
Type: String
Default: false
AllowedValues: [true, false]
Resources:
BasicSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable www port
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
VpcId: !Ref VpcId
MyInstance1:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT5M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance1 \
--region ${AWS::Region}
MyNLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
LoadBalancerAttributes:
- Key: load_balancing.cross_zone.enabled
Value: !Ref CrossZoneEnabled
Scheme: internet-facing
Subnets: !Ref NLBSubnetsIds
Type: network
MyListner1:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref MyTargetGroup
Type: forward
LoadBalancerArn: !Ref MyNLB
Port: 80
Protocol: TCP
MyTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 10
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthyThresholdCount: 2
UnhealthyThresholdCount: 2
Port: 80
Protocol: TCP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 30
Targets:
- Id: !Ref MyInstance1
Port: 80
TargetType: instance
VpcId: !Ref VpcId
Outputs:
DNSName:
Value: !GetAtt MyNLB.DNSName
从 end-user 的角度来看,在您的场景中,在 NLB 中启用或禁用 [=65=] 之间没有明显区别。但是,long-term 差异可能在于 高可用性 。也就是说,如果您禁用了 cross-zone,并且如果实例所在 AZ 中的 NLB 节点出现问题,NLB 将无法将流量从其他 AZ 路由到您的实例。这是我的猜测,因为这不是您可以手动检查的内容。原因是,一旦您将 AZ/subnet 与您的 NLB 关联,就无法取消关联,以检查在这种情况下会发生什么。
相反,如果启用 cross-zone,在上述情况下,来自其他区域的 NLB 节点可能会将流量路由到跨区域的实例。
启用 cross-zone 流量的主要好处是当您 different number of instances 在不同的可用区时。在这种情况下,cross-zone 平衡使所有实例将获得大致相同的流量。如果没有 cross-zone 平衡,隔离实例将获得比其他 AZ 中的实例集合更多的流量。
您可以使用 第二个模板 检查 zone-balancing 的效果。模板和之前差不多,但是现在1个AZ有3个实例,而另一个有1个AZ。
---
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
NLBSubnetsIds:
Type: List<AWS::EC2::Subnet::Id>
InstanceSubnetId1:
Type: AWS::EC2::Subnet::Id
InstanceSubnetId2:
Type: AWS::EC2::Subnet::Id
AmazonLinux2AMIId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
CrossZoneEnabled:
Type: String
Default: false
AllowedValues: [true, false]
Resources:
BasicSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable www port
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
VpcId: !Ref VpcId
MyInstance1:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId1
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance1 \
--region ${AWS::Region}
MyInstance2:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId2
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello2 world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance2 \
--region ${AWS::Region}
MyInstance3:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId2
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello2 world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance3 \
--region ${AWS::Region}
MyInstance4:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId2
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello2 world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance4 \
--region ${AWS::Region}
MyNLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
LoadBalancerAttributes:
- Key: load_balancing.cross_zone.enabled
Value: !Ref CrossZoneEnabled
Scheme: internet-facing
Subnets: !Ref NLBSubnetsIds
Type: network
MyListner1:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref MyTargetGroup
Type: forward
LoadBalancerArn: !Ref MyNLB
Port: 80
Protocol: TCP
MyTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 10
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthyThresholdCount: 2
UnhealthyThresholdCount: 2
Port: 80
Protocol: TCP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 30
Targets:
- Id: !Ref MyInstance1
Port: 80
- Id: !Ref MyInstance2
Port: 80
- Id: !Ref MyInstance3
Port: 80
- Id: !Ref MyInstance4
Port: 80
TargetType: instance
VpcId: !Ref VpcId
Outputs:
DNSName:
Value: !GetAtt MyNLB.DNSName
如果您使用上述模板,并重复请求 NLB url,您将看到隔离实例将获得大约 50% 的流量而没有 cross-zone 平衡。启用 cross-zone 平衡后,约为 20%。以下是我基于 100 个请求的结果:
您的方案不需要启用跨区域负载平衡。正如 Marcin 指出的那样,它对您没有任何作用。事实上,解析您的 NLB 的 DNS,您会看到它只有 returns 每个 AZ 的 A 记录,该 AZ 在 NLB 的所有目标组中聚合了一个健康的实例。 Marcin 的回应非常适合深入探讨。
有些人在这里说“是的,但我们仍然会超时。”。这是因为您的场景比 OP 更复杂。简而言之,您可能拥有一个包含多个目标组的 NLB,其中多个 AZ 中存在不同的目标。启用跨区域负载平衡将解决您的次优配置问题,但代价是账单上会产生额外的数据传输费用。 Duck tape 和 gum wrappers 在 AWS VPC 中工作。
更多信息:
NLB 对 DNS 很“聪明”,因为它们的 VIP 只会解析到具有健康目标的 A 记录(在及时的原因内)。如果一个 NLB 有几个目标组,这些目标组在三个 AZ 中具有不同的实例,您将获得三个返回的 A 记录(每个 AZ 都有一个健康目标)。这就是 NLB + RR DNS 的工作原理。
但是,如果您的目标组在单个 AZ 中包含 EC2 实例,则 DNS 循环法将解析正确 AZ 的可能性为 33%(给定三个 AZ)。
最好的解决办法是开启跨区负载均衡。这会增加数据传输成本,但与断开 NLB 的替代方案相比,它没有那么复杂。请注意,启用跨区域负载平衡需要几分钟才能生效。不要启用它,立即启动一个 telnet,当它不起作用时会很伤心。等待 5 - 10 分钟,然后启动您的 telnet。
资料来源:使用 AWS 和 janky EC2 解决方案的轶事和实践经验。
在 AWS 网络负载均衡器文档中,它说当为目标组指定实例时,它必须在负载均衡器注册的每个 AZ 中包含一个实例。这不是强制执行的。
如果您在 3 个 AZ 中注册了一个 NLB,但在 AZ1 中只有一个目标 EC2 实例,流量会怎样?如果您启用跨 AZ 负载平衡,会有什么不同吗?
What happens to traffic if you have an NLB registered in 3 AZs, but only a single target EC2 instance in AZ1? What if you enable cross AZ load balancing, does that make any difference?
在此特定场景中(NLB 在 3 个可用区中,单个实例在 1 个可用区中),什么都没有发生。从 end-user 的角度来看,有或没有 cross-zone 负载平衡没有明显的区别。在任何一种情况下都可以访问该实例。
为了验证这一点,我开发了一个简单的 CloudFormation 模板,它创建了 NLB,有或没有 cross-zone 负载平衡,以及 1 个实例。该模板允许使用不同的 NLB、cross-zone 和实例位置进行 简单实验 。我在 us-east-1
区域和默认 VPC 中使用了模板。
您为模板指定了几个参数,包括:
NLBSubnetsIds - 启用 NLB 的子网。您必须先在控制台中检查,哪些子网在哪些可用区中。
InstanceSubnetId - 实例的子网。如果您想使用实例位置,您可以再次检查哪个子网在哪个 AZ 中。您必须确保在为您的 NLB 设置的可用区之一中创建该实例。
CrossZoneEnabled - 为 NLB 启用或禁用 [=65=] 平衡。
从模板创建堆栈并通过实例健康检查(可能需要 1 或 2 分钟)后,您可以在浏览器中访问 NLB DNS 以查看托管的示例网页 在实例上。
---
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
NLBSubnetsIds:
Type: List<AWS::EC2::Subnet::Id>
InstanceSubnetId:
Type: AWS::EC2::Subnet::Id
AmazonLinux2AMIId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
CrossZoneEnabled:
Type: String
Default: false
AllowedValues: [true, false]
Resources:
BasicSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable www port
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
VpcId: !Ref VpcId
MyInstance1:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT5M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance1 \
--region ${AWS::Region}
MyNLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
LoadBalancerAttributes:
- Key: load_balancing.cross_zone.enabled
Value: !Ref CrossZoneEnabled
Scheme: internet-facing
Subnets: !Ref NLBSubnetsIds
Type: network
MyListner1:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref MyTargetGroup
Type: forward
LoadBalancerArn: !Ref MyNLB
Port: 80
Protocol: TCP
MyTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 10
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthyThresholdCount: 2
UnhealthyThresholdCount: 2
Port: 80
Protocol: TCP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 30
Targets:
- Id: !Ref MyInstance1
Port: 80
TargetType: instance
VpcId: !Ref VpcId
Outputs:
DNSName:
Value: !GetAtt MyNLB.DNSName
从 end-user 的角度来看,在您的场景中,在 NLB 中启用或禁用 [=65=] 之间没有明显区别。但是,long-term 差异可能在于 高可用性 。也就是说,如果您禁用了 cross-zone,并且如果实例所在 AZ 中的 NLB 节点出现问题,NLB 将无法将流量从其他 AZ 路由到您的实例。这是我的猜测,因为这不是您可以手动检查的内容。原因是,一旦您将 AZ/subnet 与您的 NLB 关联,就无法取消关联,以检查在这种情况下会发生什么。
相反,如果启用 cross-zone,在上述情况下,来自其他区域的 NLB 节点可能会将流量路由到跨区域的实例。
启用 cross-zone 流量的主要好处是当您 different number of instances 在不同的可用区时。在这种情况下,cross-zone 平衡使所有实例将获得大致相同的流量。如果没有 cross-zone 平衡,隔离实例将获得比其他 AZ 中的实例集合更多的流量。
您可以使用 第二个模板 检查 zone-balancing 的效果。模板和之前差不多,但是现在1个AZ有3个实例,而另一个有1个AZ。
---
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
NLBSubnetsIds:
Type: List<AWS::EC2::Subnet::Id>
InstanceSubnetId1:
Type: AWS::EC2::Subnet::Id
InstanceSubnetId2:
Type: AWS::EC2::Subnet::Id
AmazonLinux2AMIId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
CrossZoneEnabled:
Type: String
Default: false
AllowedValues: [true, false]
Resources:
BasicSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable www port
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
VpcId: !Ref VpcId
MyInstance1:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId1
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance1 \
--region ${AWS::Region}
MyInstance2:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId2
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello2 world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance2 \
--region ${AWS::Region}
MyInstance3:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId2
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello2 world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance3 \
--region ${AWS::Region}
MyInstance4:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT3M
Properties:
ImageId: !Ref AmazonLinux2AMIId
InstanceType: t2.micro
Monitoring: false
SecurityGroupIds: [!Ref BasicSecurityGroup]
SubnetId: !Ref InstanceSubnetId2
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum install -y httpd aws-cfn-bootstrap
echo "<h2>Hello2 world from $(hostname -f)</h2>" \
> /var/www/html/index.html
systemctl start httpd
# check if website is working
curl -s localhost | grep "Hello"
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource MyInstance4 \
--region ${AWS::Region}
MyNLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
LoadBalancerAttributes:
- Key: load_balancing.cross_zone.enabled
Value: !Ref CrossZoneEnabled
Scheme: internet-facing
Subnets: !Ref NLBSubnetsIds
Type: network
MyListner1:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref MyTargetGroup
Type: forward
LoadBalancerArn: !Ref MyNLB
Port: 80
Protocol: TCP
MyTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 10
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthyThresholdCount: 2
UnhealthyThresholdCount: 2
Port: 80
Protocol: TCP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 30
Targets:
- Id: !Ref MyInstance1
Port: 80
- Id: !Ref MyInstance2
Port: 80
- Id: !Ref MyInstance3
Port: 80
- Id: !Ref MyInstance4
Port: 80
TargetType: instance
VpcId: !Ref VpcId
Outputs:
DNSName:
Value: !GetAtt MyNLB.DNSName
如果您使用上述模板,并重复请求 NLB url,您将看到隔离实例将获得大约 50% 的流量而没有 cross-zone 平衡。启用 cross-zone 平衡后,约为 20%。以下是我基于 100 个请求的结果:
您的方案不需要启用跨区域负载平衡。正如 Marcin 指出的那样,它对您没有任何作用。事实上,解析您的 NLB 的 DNS,您会看到它只有 returns 每个 AZ 的 A 记录,该 AZ 在 NLB 的所有目标组中聚合了一个健康的实例。 Marcin 的回应非常适合深入探讨。
有些人在这里说“是的,但我们仍然会超时。”。这是因为您的场景比 OP 更复杂。简而言之,您可能拥有一个包含多个目标组的 NLB,其中多个 AZ 中存在不同的目标。启用跨区域负载平衡将解决您的次优配置问题,但代价是账单上会产生额外的数据传输费用。 Duck tape 和 gum wrappers 在 AWS VPC 中工作。
更多信息:
NLB 对 DNS 很“聪明”,因为它们的 VIP 只会解析到具有健康目标的 A 记录(在及时的原因内)。如果一个 NLB 有几个目标组,这些目标组在三个 AZ 中具有不同的实例,您将获得三个返回的 A 记录(每个 AZ 都有一个健康目标)。这就是 NLB + RR DNS 的工作原理。
但是,如果您的目标组在单个 AZ 中包含 EC2 实例,则 DNS 循环法将解析正确 AZ 的可能性为 33%(给定三个 AZ)。
最好的解决办法是开启跨区负载均衡。这会增加数据传输成本,但与断开 NLB 的替代方案相比,它没有那么复杂。请注意,启用跨区域负载平衡需要几分钟才能生效。不要启用它,立即启动一个 telnet,当它不起作用时会很伤心。等待 5 - 10 分钟,然后启动您的 telnet。
资料来源:使用 AWS 和 janky EC2 解决方案的轶事和实践经验。