AWS Elastic Load Balancer:将请求转发到所有实例

AWS Elastic Load Balancer:将请求转发到所有实例

使用 Terraform 在 AWS 中创建自动缩放组(具有 2 个实例)和弹性负载均衡器 (ELB)。

实例运行简单http-echo在端口 3000 上用 Go 编写的服务器。

当通过浏览器访问负载均衡器的 DNS 名称时,请求会记录在两个实例中,而不是一个实例中。预期行为应该是将请求发送到其中一个实例。

实例1的日志:

2019/01/23 05:03:53 <DNS Name of LB> 
10.0.21.217:31904 "GET /favicon.ico HTTP/1.1" 200 58 
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/71.0.3578.98 Safari/537.36" 9.018µs

实例2的日志:

2019/01/23 05:03:53 <DNS Name of LB> 
10.0.21.217:47620 "GET / HTTP/1.1" 200 58 
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/71.0.3578.98 Safari/537.36" 9.074µs

但是当请求发送curl到同一地址时,负载均衡器会按预期工作,只将请求发送到其中一个实例,并且还会在重复请求时循环遍历这些实例。这是期望的行为。

请求日志curl

2019/01/23 05:43:15 <DNS Name of LB> 10.0.21.217:49364 
"GET / HTTP/1.1" 200 58 "curl/7.47.0" 8.397µs

两个实例均“健康”,并响应负载均衡器的健康请求。

负载均衡器的配置如下:

resource "aws_elb" "go_app" {
  name               = "terraform-asg-go-app"
  security_groups    = ["${aws_security_group.elastic_lb.id}"]
  subnets            = ["${aws_subnet.public.*.id}"]

  listener {
    lb_port           = 80
    lb_protocol       = "http"
    instance_port     = 3000
    instance_protocol = "http"
  }

  cross_zone_load_balancing   = true
  idle_timeout                = 400
  connection_draining         = true
  connection_draining_timeout = 400
}

负载均衡器的安全组具有以下配置:

resource "aws_security_group" "elastic_lb" {
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

虽然实例的安全组有以下配置:

resource "aws_security_group" "go_app" {    
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 3000 
    to_port     = 3000
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

答案1

这是预期行为。查看两个实例中获取的路径 -

实例1

10.0.21.217:31904 "GET /favicon.ico HTTP/1.1" 200 58 

实例2

10.0.21.217:47620 "GET / HTTP/1.1" 200 58

第二个请求获取页面本身,第一个请求获取网站图标页面的。部署 Web 应用时,浏览器会分离请求获取与您的 Web 应用相关的所有资产,图标就是其中一种资产。其他资产可能是 css/js 文件、图像等。所有引用的资产均单独获取,并且然后呈现在页面上。

当浏览器发出多个请求时,它们会到达负载均衡器,然后负载均衡器会将请求分配给其后面的实例,通常采用循环方式,这就是为什么您会在两个实例上看到单独的请求。

curl另一方面,只是获取 html 页面并且不发出任何额外请求。

答案2

再次仔细检查上面发布的日志。您的 Chrome 发出两个请求:

  1. GET / HTTP/1.1
  2. GET /favicon.ico HTTP/1.1

并且由于负载均衡器是负载平衡的,它会按预期向每个节点发送一个请求。

向所有网站发出请求以便它们可以在书签、标签等中显示网站图标是现代桌面浏览器的标准行为。/favicon.ico另一方面,curl不执行此操作,因此您只会看到一个请求。

希望有帮助:)

相关内容