Назад | Перейти на главную страницу

AWS Elastic Load Balancer: пересылка запросов всем инстансам

Использование Terraform для создания Autoscaling Group (с двумя экземплярами) и Elastic Load Balancer (ELB) в AWS.

Экземпляры работают просто http-echo сервер написан на Go на порт 3000.

Когда DNS-имя Load Balancer посещается через браузер, запрос регистрируется в обоих экземплярах, а не в одном. Ожидаемое поведение должно заключаться в отправке запроса в один из экземпляров.

Журнал 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

Оба экземпляра «исправны» и отвечают на запросы о работоспособности Load Balancer.

Конфигурация Load Balancer приведена ниже:

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"]
  }
}

Это ожидаемое поведение. Посмотрите на пути, которые выбираются в обоих случаях -

Instance1

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

Instance2

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

Второй извлекает саму страницу, а первый запрос извлекает фавикон страницы. Когда вы развертываете веб-приложение, браузер делает отдельный запросы на выборку всех ресурсов, связанных с вашим веб-приложением, одним из которых является значок favicon. Другими активами могут быть файлы css / js, изображения и т. Д. Все указанные ресурсы извлекаются отдельно и затем отображается на странице.

Когда браузер делает несколько запросов, они попадают в балансировщик нагрузки, который затем распределяет запрос между экземплярами, стоящими за ним, как правило, циклически, поэтому вы видите отдельные запросы на двух экземплярах.

curl с другой стороны, просто получает HTML-страницу и не делает никаких дополнительных запросов.

Еще раз внимательно проверьте опубликованные выше журналы. Ваш Chrome делает два запроса:

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

И поскольку балансировщик нагрузки выполняет балансировку нагрузки, он отправляет по одному запросу на каждый узел, как и ожидалось.

Стандартное поведение современных настольных браузеров - запрашивать /favicon.ico со всех веб-сайтов, чтобы они могли отображать значок сайта в закладках, вкладках и т. д. С другой стороны curl не делает этого, поэтому вы видите только один запрос.

Надеюсь, это поможет :)