Статьи

Использование HAProxy в качестве обратного прокси-сервера для микросервисов AWS

Микроэкземпляры Amazon EC2 предлагают очень доступный вариант размещения архитектуры микросервисов на основе Docker. Каждый микроэкземпляр может содержать несколько контейнеров Docker. Например, у вас может быть простое веб-приложение на основе Node.js, которое вы хотели бы отобразить как subdomain1.myhost.com, и другое веб-приложение Java / Tomcat, появившееся на subdomain2.myhost.com. Каждый из них может быть размещен через отдельный (и, возможно, кластерный) контейнер Docker с дополнительными контейнерами, используемыми для предоставления API-сервисов. Архитектура может напоминать:

AwsDockerReverseProxy

Обратите внимание на использование HAProxy, который используется в этом случае в качестве балансировщика нагрузки и обратного прокси-сервера. Он размещается в своем собственном экземпляре micro-EC2 и будет направлять входящий трафик к своему месту назначения на основе правил маршрутизации на субдоменах (HAProxy поддерживает широкий спектр рутинных правил, в отличие от Apache mod_proxy). Обе записи DNS для subdomain1 и subdomain2 будут направлять трафик на один и тот же общедоступный IP-адрес, который в этом случае перехватывается HAProxy. Правила маршрутизации конфигурации затем перенаправят входящий запрос в соответствующий контейнер Docker, на котором размещен веб-сайт.

Настройка HAProxy очень проста, что может объяснить его популярность в сообществе открытого исходного кода (узнайте больше о HAProxy на http://www.haproxy.org/ ). Давайте рассмотрим пример файла конфигурации HAProxy, который будет поддерживать вышеуказанную архитектуру (haproxy.cfg обычно находится в / etc / haproxy). Мы начнем с двух глобальных секций и секций по умолчанию, которые вы, скорее всего, можете оставить «как есть» для большинства сценариев:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
global
        maxconn 4096
        user haproxy
        group haproxy
        daemon
        log 127.0.0.1 local0 debug
 
defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        retries 3
        option redispatch
        option http-server-close
        option forwardfor
        maxconn 2000
        timeout connect 5s
        timeout client  15min
        timeout server  15min

Далее мы перейдем к разделу «внешний интерфейс», который используется для описания набора прослушивающих сокетов, принимающих клиентские подключения, и используется для настройки правил переадресации IP / портов, которые перенаправляют трафик на соответствующий хост для обработки. ,

01
02
03
04
05
06
07
08
09
10
frontend public
        bind *:80
 
        # Define hosts
        acl host_subdomain1 hdr(host) -i subdomain1.myhost.com
        acl host_subdomain2 hdr(host) -i subdomain2.myhost.com
 
        ## figure out which one to use
        use_backend subdomain1 if host_subdomain1
        use_backend subdomain2 if host_subdomain2

Директива «bind» используется для указания того, какой порт HAProxy будет прослушивать (в данном случае, порт 80). Директивы «acl» определяют критерии для маршрутизации входящего трафика. Первый параметр, следующий за директивой, является просто внутренним именем для будущей ссылки, а остальные параметры определяют методы, используемые для сопоставления некоторого элемента входящего запроса, который используется в качестве основы для маршрутизации (документы HAProxy предоставляют более подробную информацию. ). В этом случае первая директива «acl» просто заявляет, что если входящий запрос имеет имя хоста «subdomain1.myhost.com», то назначьте совпадение идентификатору acl, называемому «host_subdomain1». По сути, мы просто определяем критерии для соответствия входящего запроса.

Следующая часть этого раздела — директива use_backend, которая назначает соответствующее правило acl конкретному хосту для обработки. Итак, в первом примере говорится, что если имя совпадения «acl» для входящего запроса назначено «host_subdomain1», то используйте бэкэнд, обозначенный «subdomain1». Эти «бэкэнды» определены в следующем разделе:

01
02
03
04
05
06
07
08
09
10
11
backend subdomain1
        option httpclose
        option forwardfor
        cookie JSESSIONID prefix
        server subdomain-1 someawshost.amazonaws.com:8080 check
 
backend subdomain2
        option httpclose
        option forwardfor
        cookie JSESSIONID prefix
        server subdomain-2 localhost:8080 check

В первой директиве «backend» мы определяем серверную часть, используемую для обработки, которая была идентифицирована через присвоенное имя «subdomain1» (это просто произвольные имена — просто убедитесь, что они совпадают с тем, что есть в директиве frontend). Директива «server» (в которой в качестве первого параметра используется произвольное присвоение имени) затем используется для определения хоста / порта для пересылки запроса, который в данном случае является хостом someawshost.amazonaws.com:8080 (параметр check актуально только при использовании балансировки нагрузки). Вы можете определить несколько директив сервера, если используете балансировку нагрузки / кластеризацию.

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

API и микросервисы

Одна из проблем при разработке API-решения, работающего с использованием микросервисов, заключается в том, как «разделить» различные сервисные вызовы, чтобы они могли размещаться в отдельных контейнерах Docker. Использование подхода, основанного на поддоменах (то есть subdomain.myhost.com), который я описал ранее для стандартных веб-приложений, не очень практичен, когда вы хотите предоставить единый API своему сообществу разработчиков. Тем не менее, это все еще может быть выполнено во многом таким же образом, используя правила обратного прокси на основе URL-пути. Например, рассмотрим эти два вымышленных вызова API:

1
2
GET api.mycompany.com/contracts/{contractId}
GET api.mycompany.com/customers/{customerId}

В первом примере это вызов RESTful GET, который извлекает данный объект JSON контракта на основе указанного ContractId. Аналогичный шаблон используется в примере 2 для извлечения записи клиента. Как видите, первый элемент пути — это действительно «домен», связанный с вызовом веб-службы. Это может быть использовано в качестве основы для разделения вызовов этих доменов на их собственные отдельные контейнеры Docker микросервиса. Хорошая выгода от этого заключается в том, что один из этих доменов может обычно получать больше трафика, чем другой. Разделив их на отдельные службы, вы можете выполнить целевое масштабирование.

Если вам понравилась эта статья, пожалуйста, ссылку на нее соответственно.