Amazon-Web-Services

AWS Elastic Load Balancer:將請求轉發到所有實例

  • January 23, 2019

使用 Terraform 在 AWS 中創建 Autoscaling Group(具有 2 個實例)和 Elastic Load Balancer (ELB)。

這些實例在埠 3000 上執行用 Go 編寫的簡單http-echo伺服器。

當通過瀏覽器訪問負載均衡器的 DNS 名稱時,請求會記錄在兩個實例中而不是一個實例中。預期的行為應該是向其中一個實例發送請求。

Instance1 的日誌:

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

Instance2 的日誌:

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

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 應用程序相關的所有資產,favicon 就是這樣一種資產。其他資產可能是 css/js 文件、圖像等。所有引用的資產都是單獨獲取的,然後在頁面上呈現。

當瀏覽器發出多個請求時,它們會點擊負載均衡器,然後負載均衡器會在其後面的實例之間分配請求,通常以循環方式進行,這就是為什麼您在兩個實例上看到單獨的請求的原因。

curl另一方面,只是獲取 html 頁面並且不發出任何額外的請求。

引用自:https://serverfault.com/questions/950315