Микросервисы Hydra для разработчика ExpressJS

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

Однако по мере роста количества микросервисов растет и количество промежуточных решений, используемых для их связывания. Добавьте несколько микросервисов, и им понадобится способ маршрутизации сообщений к каждому из них. Итак, введите Nginx, чтобы решить эту проблему. Может быть, некоторым микросервисам нужно общаться друг с другом? Хм, хорошо, использовать HTTP-вызовы Rest между службами? Или, возможно, используйте службу очереди сообщений, такую ​​как MQTT, RabbitMQ или Kafka. Как насчет мониторинга микросервисов? Что ж, там много решений! В целом, каждая проблема требует от вас изучения новой технологии и написания кода, чтобы связать все это.

Хорошая новость в том, что недостатка в решениях нет. Единственная реальная нехватка - это ваше время. Но, как я говорил днем ​​... ночь еще молода.

По правде говоря, микросервисы - это не шутки. И это справедливо для распределенных приложений в целом. Проблема в том, что код не находится в одном месте - вместо этого он должен обмениваться данными по сети.

Дополнительные проблемы могут не показаться большой проблемой для команд с большим опытом. Но что, если только вы или ваша команда на самом деле этого не делали? Как опытный разработчик ExpressJS создает надежные микросервисы?

Hydra - это единый пакет NPM, предназначенный для решения вышеуказанных проблем и многого другого. С помощью Hydra вы можете создавать, настраивать и развертывать микросервисы в рекордно короткие сроки. Однако есть одна небольшая загвоздка ... Вам понадобится экземпляр Redis. Учитывая, что на протяжении многих лет Redis выбирался разработчиками как одна из наших самых любимых и востребованных баз данных, вполне вероятно, что вы уже используете Redis или знаете кого-то, кто им пользуется. Если нет, не беспокойтесь - вы будете использовать Redis к концу этого поста.

В этом посте я предполагаю, что вы хорошо знакомы с NodeJS и ExpressJS, но, возможно, у вас мало опыта в создании сложных микросервисов. Если это не вы, то подыграйте - наверняка есть несколько интересных моментов, которые вы можете убрать.

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

Настройка Redis

Ранее я упоминал, что Hydra требует Redis. Если у вас уже есть доступ к экземпляру Redis, вы можете безопасно отправить этот раздел.

Безусловно, самый простой и полезный способ запустить Redis - это просто установить Docker и запустить Redis как контейнер.

См. Это руководство по быстрому запуску, и Redis должен быть запущен менее чем за 10 минут. И ... есть масса других руководств по началу работы с Redis.

Покажи мне код!

На этом этапе у вас должен быть доступ к работающему экземпляру Redis. А теперь мы готовы поиграться с кодом.

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

Введите: git clone https://github.com/cjus/hydra-intro.git, чтобы получить это репо.

Запустите файл stackup.sh, чтобы запустить тестовый кластер докеров с Redis. Если вам интересно, вы можете просмотреть файл compose.yml, чтобы ознакомиться с особенностями Redis.

Все примеры кода находятся в папке examples. В процессе подготовки перейдите в папку примеров и запустите npm install

Начнем с рассмотрения упрощенного примера ExpressJS. Конечно, ваше экспресс-приложение могло быть давно не таким простым.

Версия Hydra немного длиннее, так что давайте рассмотрим ее подробнее.

Начнем с загрузки гидра-экспресса на первую линию. HydraExpress - это привязка Hydra и ExpressJS. Поэтому при использовании HydraExpress вам не нужно также включать ExpressJS, потому что HydraExpress уже делает это. Используя ссылку на Hydra, мы просим ее указать ссылку на ExpressJS во второй строке.

В третьей строке мы получаем ссылку на роутер Express.

В строке 6 мы инициализируем HydraExpress с помощью внешнего файла конфигурации, который мы вскоре рассмотрим. Функция init требует обратного вызова в качестве второго параметра, который будет автоматически вызываться, когда HydraExpress будет готов зарегистрировать ваши маршруты.

Мы используем ссылку на маршрутизатор ExpressJS (api) в строке 7 для определения корневого маршрута. Затем в строке 10 мы просто регистрируем маршрут.

Прокрутите назад и сравните два примера - они действительно очень похожи!

Давайте посмотрим на файл hello-config.json, указанный в строке 6.

Это стандартный файл конфигурации Hydra. Он начинается с ключа гидры, указывающего на объект. Мы определяем наши serviceName и servicePort. serviceIP и serviceType не являются обязательными. Действительно важным ключом является ключ redis в строке 8. Здесь мы сообщаем Гидре, что Redis может быть доступен на локальном компьютере через порт 6379. Косая черта 15 указывает, какую базу данных Redis он должен использовать.

Если вы не так хорошо знакомы с Redis, не беспокойтесь о приведенной выше конфигурации. Вы можете узнать об этом больше позже, когда попытаетесь указать на удаленные серверы Redis.

Итак, мы сравнили простое приложение ExpressJS с приложением HydraExpress. Версия Hydra определенно требует немного больше работы - нам нужно ввести еще шесть строк кода и использовать внешний файл конфигурации. Конечно, в более сложном проекте эти незначительные отличия будут наименьшей из наших проблем. Тем не менее, что мы получаем от версии HydraExpress, чего нет в базовом приложении ExpressJS? В конце концов, оба примера делают то же самое при доступе через http://127.0.0.1:8080

Чтобы начать отвечать на этот вопрос, давайте взглянем на второй, немного более сложный пример Гидры под названием hello-inst.js.

Код добавляет одну строку (# 2) и изменяет существующую строку (# 9) в предыдущем примере hello.js.

Строка №2 запрашивает у HydraExpress ссылку на его внутренний модуль Hydra-core. Используя этот модуль, мы получаем доступ к имени нашей службы и ее instanceID в строке №9. Скоро мы увидим эти изменения в действии.

Давайте продолжим и запустим этот пример.

И давайте зайдем на http://127.0.0.1:8080 из веб-браузера.

Здесь мы видим, что, как и ожидалось, пример возвращает свои serviceName и instanceID.

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

Хорошо, давайте сделаем шаг на ступеньку выше! У наших гавайских братьев и сестер есть пиджинское изречение под названием Howsit. Переводится как «как дела», или «как дела», или «как дела». Часто слышно как «Эх, браддах, как дела!». Наше следующее приложение правильно названо: howsit.js

Эта версия такая же, как и в нашем последнем примере, за исключением изменения конфигурации в строке 7 и косметического изменения текстовой строки в строке 9.

Более интересное изменение происходит в строке 5 файла howsit-config.json, где мы изменили порт с 8080 на 0 (ноль).

Когда Hydra встречает нулевой номер порта, она автоматически назначает случайный номер порта больше 1024. Это полезно, когда вам нужно запустить несколько экземпляров вашей службы на одном компьютере, поскольку конфликтов портов можно избежать.

Если мы запустим сервис howsit, мы увидим:

Обратите внимание на новый порт 34310 выше. Доступ к http://127.0.0.1:34310 возвращает: Eh, braddah, howsit! howsit — eaf6e4e1ad0242cf96b3f3407d50120c

Прохладный. Теперь откройте дополнительные окна / панели терминала и запустите несколько экземпляров службы howsit:

К каждому из них можно получить доступ через назначенный ему номер порта. Однако, если мы потратим время на установку hydra-cli инструмента командной строки, мы увидим интересное поведение!

Нам действительно нужно настроить hydra-cli перед его использованием. А именно сказать ему, где находится Redis. Мы будем использовать те же значения в наших файлах конфигурации.

Мы можем запросить у hydra-cli список всех работающих служб (узлов):

Итак, Гидра хорошо знает о наших запущенных экземплярах!

Мы можем использовать интерфейс REST Hydra-cli для доступа к нашим сервисам. Синтаксис гласит: rest servicename: [http-method] api-path

Здесь мы видим в строке 6, что мы получили ответ от экземпляра b0c17930878548669ffd56713f3d8992. Обратите внимание, что мы не указали номер порта!

Повторение команды hydra-cli rest еще несколько раз возвращает:

“result”: “Eh, braddah, howsit! howsit — 8172eea68f4a4d0599225725cb410572”,

“result”: “Eh, braddah, howsit! howsit — eaf6e4e1ad0242cf96b3f3407d50120c”,

Таким образом, нагрузка на запросы балансируется между нашими доступными экземплярами.

Если мы остановим один из наших экземпляров и повторно введем команду hydra-cli rest, мы увидим ответы только от доступных служб. Это потому, что Hydra управляет присутствием и знает, когда экземпляр больше не доступен.

Я уверен, вы согласитесь, что мы сейчас на обновленном поезде ExpressJS!

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

Распределенным сервисам часто необходимо взаимодействовать друг с другом. Используя Hydra, это становится на удивление простым. В следующем примере мы рассмотрим две службы: send.js и recv.js, чтобы увидеть, как службы могут взаимодействовать.

Первый. давайте посмотрим на recv.js пример. Обратите внимание, что я удалил биты экспресс-маршрутизации, поскольку они не имеют отношения к нашему примеру.

В строке 6 мы настраиваем обработчик сообщений Hydra и просто выводим все приходящие сообщения.

Пример send.js намного интереснее. Здесь мы берем serviceName и instanceID и используем их для идентификации отправителя в строке 6. В строке 7 мы используем вызов hydra createUMFMessage для создания объекта сообщения с использованием обязательных полей, to, from и body.

Обратите внимание, что в строке 8 мы указываем, что сообщение должно быть доставлено службе recv.

Затем мы берем greetingMessage и отправляем его через функцию-член hydra.sendMessage. Да, отправлять сообщения действительно так просто.

Теперь давайте запустим несколько экземпляров нашей recv службы и одну send службу.

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

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

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

Следующие шаги

Ранее мы видели, что есть удобная программа hydra-cli. На самом деле доступно довольно много инструментов. Один из инструментов называется HydraRouter, микросервис на основе гидры, который может направлять входящие сообщения HTTP и Websocket на любой из ваших сервисов.

Hydra была открыта на конференции EmpireNode в 2016 году и поддерживает службу потокового видео в реальном времени FlyAnywhere. Его используют все большее количество компаний, и он может отлично подойти для вашего следующего проекта!

Ознакомьтесь с проектной документацией на HydraMicroservice.com.

Для более глубокого понимания того, как на самом деле работает Hydra, см. Мою презентацию RedisConf18.

Спасибо за внимание! Если вам нравится то, что вы читаете, удерживайте кнопку хлопка внизу, чтобы другие могли это найти. Вы также можете подписаться на меня в Twitter.