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

  • работает на AWS ECS: вся наша инфраструктура использовала AWS ECS. Я не собирался вкладывать деньги в переход на Kubernetes (хотя это более популярно и, возможно, мне стоит научиться - в другой раз я научусь самостоятельно).
  • динамический размер кластера: я хотел иметь возможность вращать узлы в кластере по мере необходимости. Во многих решениях предлагалось выделить определенные серверы и IP-адреса и чтобы каждый узел в кластере знал друг о друге из статических файлов, зафиксированных в git.
  • минимизировать изменения: в идеале изменения для создания кластера будут в основном конфигурационными. По этой причине статьи, содержащие много кода эликсира или связанные с созданием новой инфраструктуры, такой как кеш Redis, мне не нравились.

Прежде чем мы поговорим о том, как настроить кластер, давайте поговорим о том, зачем нам нужно создать кластер.

отказ от ответственности: эта статья предполагает знание AWS ECS, сетей AWS и EPMD. Если вы не знакомы с этими темами, здесь - хорошее руководство по созданию сетей AWS; Здесь - хорошее руководство по AWS ECS; а здесь - это учебник по распространяемому Эликсиру с EPMD.

Зачем нам кластер?

Представим, что мы хотим рассылать живые обновления пользователям нашего веб-сайта. Один из подходов - использовать веб-сокет, чтобы посетитель сайта оставался подключенным к серверу, а сервер мог «проталкивать» обновления по мере необходимости.

Это решение довольно простое. Как только пользователь подключается к серверу, сервер может отправлять обновления пользователю через активное соединение. Здесь мы показываем другую службу, которая сообщает серверу websocket отправлять данные пользователю.

В конце концов (надеюсь) у нас будет достаточно пользователей, чтобы нам понадобилось более одного сервера. Если вам нужно несколько серверов, вы, вероятно, будете использовать балансировщик нагрузки для равной маршрутизации запросов на разные серверы, которые у вас есть. Вот пример того, что может пойти не так в этой ситуации:

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

По этой причине нам нужно, чтобы все серверы веб-сайтов знали друг о друге. Когда несколько серверов обмениваются данными таким образом, это называется кластером . Каждый сервер в кластере называется узлом. В кластере каждый узел будет передавать изменения другим узлам кластера. Таким образом, «другая служба» может передавать данные пользователю независимо от того, к какому серверу они подключены.

Итак, теперь вопрос:

Как создать кластер?

Конечно, мы понимаем, зачем он нам нужен. Но как на самом деле его сделать? Это может показаться сложным, но я прошел через множество разных попыток методом проб и ошибок, так что вам не придется. Вот разные части и то, как они сочетаются друг с другом.

Поскольку мы используем ECS, сначала нам нужно создать определение задачи:

Затем создайте новую службу в своем кластере ECS. Сделайте это сервисом FARGATE и дайте ему несколько подсетей в VPC. Убедитесь, что для каждой задачи создается новый ENI и для службы включено обнаружение службы на основе IP (поскольку каждый ENI получит свой собственный IP-адрес).

Затем нам нужно иметь способ запустить EPMD на работающем сервере, дать серверу имя узла и подключить его к другому узлу (или узлам). Я сделал это прямо в коде эликсира с контроллером Phoenix:

Теперь при запуске новой задачи мы можем:

  • запустить EPMD
  • запустить узел
  • подключить узел к кластеру

Наконец, нам нужно что-то для выполнения этих трех вещей (поскольку они не выполняются автоматически при запуске задачи). Я добился этого с помощью небольшого скрипта Python, который запускается на AWS Lambda каждые несколько минут. Вот сценарий:

И это все!

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