使用 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 发出两个请求:
GET / HTTP/1.1
GET /favicon.ico HTTP/1.1
并且由于负载均衡器是负载平衡的,它会按预期向每个节点发送一个请求。
向所有网站发出请求以便它们可以在书签、标签等中显示网站图标是现代桌面浏览器的标准行为。/favicon.ico
另一方面,curl
不执行此操作,因此您只会看到一个请求。
希望有帮助:)