Все приложение состоит из двух серверов (RabbitMQ и Tomcat) и БД, работающей за ALB. На данный момент будет только один экземпляр RabbitMQ и один экземпляр Tomcat, однако настройка должна позволять масштабирование. Оба сервера работают в собственных контейнерах Docker. Для этого я использую ECS и CloudFormation.
Проблема с сервером RabbitMQ. Этот сервер должен прослушивать два разных порта - один для соединений WebSocket (порт 15674), а другой - для соединений HTTP для Management API (порт 15672). Соединения WebSocket устанавливаются из клиентов / браузеров. HTTP-соединения происходят внутренне от Tomcat к RabbitMQ, но они также проходят через ALB. Я не могу найти способ настроить контейнер RabbitMQ, чтобы трафик шел к нему через оба порта. Я использую части шаблона CloudFormation, относящиеся к серверу RabbitMQ. Используя этот шаблон, соединения WebSocket, похоже, работают нормально, но соединения HTTP завершаются с ошибкой 404. Приветствуются идеи, как включить HTTP-соединения (порт 15672).
ECSAutoScalingGroup:
Type: "AWS::AutoScaling::AutoScalingGroup"
Properties:
VPCZoneIdentifier:
- Ref: "Subnet1"
- Ref: "Subnet2"
LaunchConfigurationName: !Ref "AutoScalingGroupConfig"
MinSize: "1"
MaxSize: "1"
DesiredCapacity: "1"
CreationPolicy:
ResourceSignal:
Timeout: "PT5M"
UpdatePolicy:
AutoScalingReplacingUpdate:
WillReplace: true
...
ECSALB:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
DependsOn: "AttachGateway"
Properties:
Name: "ECSALB"
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: 30
Subnets:
- Ref: "Subnet1"
- Ref: "Subnet2"
SecurityGroups: [!Ref "LoadBalancerSecurityGroup"]
...
ALBRabbitMQManagementListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
DependsOn: [ "ECSServiceRole", "RabbitMQTargetGroup" ]
Properties:
DefaultActions:
- Type: "forward"
TargetGroupArn: !Ref "RabbitMQTargetGroup"
LoadBalancerArn: !Ref "ECSALB"
Port: 15672
Protocol: "HTTP"
...
ALBListenerHTTPS:
Type: "AWS::ElasticLoadBalancingV2::Listener"
DependsOn: [ "ECSServiceRole", "ECSALB" ]
Properties:
Certificates:
- CertificateArn: “some_certificate”
DefaultActions:
- Type: "redirect"
RedirectConfig:
Protocol: "HTTPS"
Host: "static.domain.com"
Path: "/#{path}"
Query: "#{query}"
StatusCode: "HTTP_301"
LoadBalancerArn: !Ref "ECSALB"
Port: 443
Protocol: "HTTPS"
...
ECSALBListenerRuleWebSocket:
Type: "AWS::ElasticLoadBalancingV2::ListenerRule"
DependsOn: [ "ALBListenerHTTPS", "RabbitMQTargetGroup" ]
Properties:
Actions:
- Type: "forward"
TargetGroupArn: !Ref "RabbitMQTargetGroup"
Conditions:
- Field: "path-pattern"
Values: [ "/ws" ]
ListenerArn: !Ref "ALBListenerHTTPS"
Priority: 2
...
RabbitMQTargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
DependsOn: "ECSALB"
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckPort: 15672
HealthCheckProtocol: "HTTP"
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
Name: "RabbitMQTargetGroup"
Port: 15674
Protocol: "HTTP"
TargetGroupAttributes:
- Key: "stickiness.enabled"
Value: true # Needed to support WebSockets
- Key: "stickiness.lb_cookie.duration_seconds"
Value: 604800 # One week (this is the maximum)
UnhealthyThresholdCount: 3
VpcId: !Ref "Vpc"
...
RabbitMQService:
Type: AWS::ECS::Service
DependsOn: [ "ALBListenerHTTPS", "RabbitMQTargetGroup", "ECSALBListenerRuleWebSocket" ]
Properties:
Cluster: !Ref “MyCluster"
Role: !Ref "ECSServiceRole"
DesiredCount: 1
TaskDefinition: !Ref "RabbitMQTask"
DeploymentConfiguration:
MinimumHealthyPercent: 100
LoadBalancers:
- ContainerName: "rabbitmq-service"
ContainerPort: 15674
TargetGroupArn: !Ref "RabbitMQTargetGroup"
...
RabbitMQTask:
Type: "AWS::ECS::TaskDefinition"
Properties:
Family: "rabbitmq-service"
NetworkMode: "host"
ContainerDefinitions:
- Name: "rabbitmq-service"
Essential: true
Image: “some_docker_image”
MemoryReservation: 1024
PortMappings:
- ContainerPort: 15672
- ContainerPort: 15674
LogConfiguration:
LogDriver: "awslogs"
Options:
awslogs-group: "rabbitmq"
awslogs-region: !Ref "AWS::Region"
awslogs-stream-prefix: “my_prefix”
awslogs-datetime-format: "%Y-%m-%d %H:%M:%S.%L"