Все завернуто в простой, воспроизводимый и поддерживаемый процесс

Об этой статье

Стандартная реализация Netflix Conductor настроена на использование Elasticsearch 6. В этой статье рассматриваются изменения, которые необходимо внести для использования Elasticsearch 7 и PostgreSQL, а также предоставляется несколько сценариев для автоматизации сборки и запуска Conductor как локально, так и в облачной архитектуре. .

На момент написания последней выпущенной версией Netflix Conductor была 3.5.3. Информация в этой статье основана на версии 3.5.1, но должна быть применима (и легко изменена) к последней версии. Если у вас возникнут какие-либо проблемы, пожалуйста, дайте мне знать, и я сделаю все возможное, чтобы помочь. Еще один отличный источник помощи — Доска обсуждений Netflix Conductor.

Я запускаю весь предоставленный код на машине с Windows 10 из Git Bash, который входит в состав Git для Windows. Наша облачная архитектура работает на CentOS.

Что такое Netflix Проводник?

Netflix Conductor — это механизм оркестрации рабочих процессов, созданный Netflix для организации потоков процессов на основе микросервисов (источник: Документация Netflix Conductor). Полный список функций Netflix Conductor находится здесь, но есть несколько ключевых функций:

  • Рабочий процесс и определения задач реализованы в формате JSON. Это позволяет управлять версиями и легко поддерживать пользовательские инструменты для создания и управления рабочими процессами и задачами.
  • Задачи и работники, т. е. строительные блоки, из которых состоят рабочие процессы и микросервисы, на которых они размещаются, соответственно, полностью не зависят от языка, что позволяет выполнять реализацию на языке, наиболее подходящем для задач. Библиотеки существуют для Java, Python, .NET (бесстыдная затычка: эта разработана мной) и других.
  • Архитектура базы данных является подключаемой, что означает, что мы можем выбирать, какую базу данных мы хотим использовать для Conductor. Проводник поставляется с многочисленными готовыми плагинами, поддерживающими (среди прочего) Dynomite (также от Netflix), MySQL и PostgreSQL.
  • Netflix Conductor поставляется с (дополнительным) пользовательским интерфейсом, который позволяет анализировать и контролировать рабочие процессы, такие как (повторный) запуск, приостановка, остановка.
  • Весь проект с открытым исходным кодом активно развивается и поддерживается.

Короче говоря, Netflix Conductor позволяет автоматизировать и управлять процессами, состоящими из нескольких задач (которые сами по себе могут быть процессами), которые, возможно, необходимо выполнять последовательно, надежным, согласованным и масштабируемым образом.

В моем текущем проекте мы используем Netflix Conductor и PostgreSQL для запуска запланированных процессов ETL, создания взаимопонимания, загрузки и выгрузки файлов, а также для мониторинга и оповещения. Мы также исследовали возможности использования Conductor для автоматизации предоставления учетных записей пользователей и другой инфраструктуры.

Настройка Netflix Conductor для Elasticsearch 7

Как упоминалось во введении, стандартная реализация Netflix Conductor настроена на использование Elasticsearch 6. Поддержка Elasticsearch 7 встроена, но для ее включения необходимо внести несколько изменений. На GitHub доступна документация для внесения этих изменений, но она не кажется полностью полной. Мне нужны были изменения, которые я описываю ниже, для сборки и запуска Elasticsearch 7.

На момент написания Elasticsearch 7.17.1 является последней версией Elasticsearch 7.

Вот краткий обзор необходимых изменений (все ссылки на файлы относятся к корневой папке):

  • build.gradle — Изменить ext['elasticsearch.version'] = revElasticSearch6
    на ext['elasticsearch.version'] = revElasticSearch7
  • settings.gradle — Удалить строку include 'es6-persistence'
  • server/build.gradle — Изменить implementation project(':conductor-es6-persistence')
    на implementation project(':conductor-es7-persistence')
  • server/src/main/resources/application.properties — Изменить conductor.elasticsearch.version=6
    на conductor.elasticsearch.version=7
  • docker/docker-compose.yaml — Изменить image: elasticsearch:6.8.15
    на image: docker.elastic.co/elasticsearch/elasticsearch:7.17.1
  • test-harness/build.gradle — Изменить testImplementation project(‘:conductor-es6-persistence’)
    на testImplementation project(‘:conductor-es7-persistence’)
  • /testharness/src/test/java/com/netflix/conductor/test/integration/AbstractEndToEndTest.java — Изменить conductor.elasticsearch.version=6
    на conductor.elasticsearch.version=7

Замените DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch-oss").withTag("6.8.12"));
на DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch").withTag("7.17.1"));

Стандартный способ применить эти изменения — создать ответвление репозитория Conductor и выполнять свою работу оттуда.

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

При сборке я clone репозиторий Conductor, затем применяю несколько patch файлов, чтобы внести необходимые изменения. Хотя эти шаги немного увеличивают время сборки, я считаю, что это хороший компромисс между скоростью и поддержанием чистоты и удобства обслуживания собственного репозитория.

Вот как это работает:

  1. Клонируйте репозиторий Conductor в директорию вашего проекта.
  2. Внесите вышеуказанные изменения.
  3. В папке Conductor запустите git diff > v3.5.1-update-to-es7.patch, чтобы создать файл patch. v3.5.1 для удобства, чтобы указать, что этот патч работает только с этой версией.
  4. Скопируйте файл patch в корневой каталог, чтобы можно было безопасно удалить репозиторий Conductor и применять изменения при каждом повторном клонировании репозитория.

Вам также необходимо удалить все файлы dependencies.lock перед сборкой. Это так же просто, как запустить rm -f **/dependencies.lock.

Чтобы автоматизировать удаление файлов lock и применение патчей, я создал скрипт 01.get-conductor.sh:

Вы можете видеть, что я на самом деле применяю еще несколько патчей. Они не требуются для работы с Elasticsearch 7.

На этом этапе вы можете построить Conductor. Я создал 02.build-conductor-server.sh для этой цели:

В разделе «Собираем все вместе» я предоставлю несколько дополнительных скриптов для автоматизации клонирования, исправления и дальнейшей сборки, в том числе как использовать переменные среды для настройки Elasticsearch.

Настройка Netflix Conductor для PostgreSQL

Запуск Проводника на PostgreSQL также описан в README-файле. Запуск docker-compose -f docker-compose.yaml -f docker-compose-postgres.yaml up запустит дополнительный экземпляр контейнера для PostgreSQL и настроит Conductor для его использования.

Но в нашем случае мы хотели запустить существующую установку PostgreSQL. Кроме того, мы не хотели, чтобы объекты базы данных Conductor создавались в схеме public, как это делается по умолчанию.

Для этого нам нужно изменить файл config-postgres.properties. Это находится в папке conductor/docker/server/config. Но поскольку мы получаем репозиторий Conductor для каждой сборки, мы не можем изменить его там.

Итак, я создал папку docker в корне моего проекта, которая будет содержать все настройки файлов в папке conductor/docker. При сборке я просто копирую содержимое этой папки.

Сценарий 02.build-conductor-server.sh теперь выглядит так:

Наш локальный файл config-postgres.properties — это просто копия оригинала с измененным разделом, посвященным PostgreSQL, следующим образом:

Добавляя currentSchema к URL-адресу источника данных, мы обеспечиваем создание объектов базы данных Conductor в указанной схеме. Свойство applicationName помогает нам при отладке сеансов базы данных, если это необходимо.

За исключением того, что это не работает. Когда мы запускаем Conductor, используя только эти изменения, свойство currentSchema игнорируется и все создается в схеме public. Не круто. Я зарегистрировал ошибку против PR, которая ее вызвала.

Я избавлю вас от нескольких часов поисков, которые я провел, чтобы найти причину и просто представить «решение». Включая воздушные кавычки, потому что это больше похоже на взлом. Но это работает.

В файле postgres-persistence/src/main/java/com/netflix/conductor/postgres/config/PostgresConfiguration.java Flyway (который обрабатывает миграцию базы данных) настроен с помощью строки .schemas("public"), что приводит к игнорированию любой попытки изменить схему по умолчанию. Удаление этой строки решает проблему.

Для этого я создал v3.5.1-fix-currentSchema-override.patch и включил его в скрипт 01.get-conductor.sh.

Если вас интересуют заполнители ##, они будут заменены значениями из соответствующих переменных среды. Я доберусь до этого в разделе «Собираем все вместе». А пока просто замените их своими значениями.

Настройка архивации рабочего процесса

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

Просто добавьте conductor.workflow-status-listener.type=archive в файл config-postgres.properties.

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

Собираем все вместе

Чтобы вышеуказанное работало как локально, так и в нашей облачной среде, мы хотим использовать переменные среды для настройки Elasticsearch и PostgreSQL. Для этого обратимся к файлу startup.sh в папке conductor/docker/server/bin. Мы копируем этот файл в нашу локальную папку docker, чтобы мы могли внести некоторые изменения.

Мы добавляем следующие строки сразу после блока if..fi:

Помните те заполнители ##, которые вы видели раньше? Мы используем инструмент sed, чтобы заменить их значениями, настроенными в соответствующих переменных среды.

Для локального запуска мы добавляем переменные среды и их значения в файлы docker-compose.yaml и docker-compose-postgres.yaml, которые мы скопировали в нашу локальную папку docker. В качестве примера см. файл docker-compose-postgres.yaml:

Мы используем магическое значение host.docker.internal, чтобы указать на наш локальный экземпляр PostgreSQL, поскольку localhost не будет работать внутри контейнера Docker.

Скрипт 02.build-conductor-server.sh также копирует startup.sh.

Наконец, осталось всего несколько скриптов.

03.build-conductor-ui.sh позаботится о создании образа интерфейса Проводника:

Мы можем запустить Conductor, используя 04.run-local.sh, который на самом деле не делает больше, чем вызывает docker compose up:

Или мы можем запустить 04.run-local-postgres.sh для работы с нашей базой данных PostgreSQL:

Вот оно. Используя приведенные выше сценарии, вы сможете создать и запустить локальный экземпляр Netflix Conductor за несколько минут. И подключение сценариев к вашему любимому инструменту CI/CD также должно быть вполне выполнимым.

В заключение

Запуск Netflix Conductor с Elasticsearch 7 и PostgreSQL требует немного усилий, но, используя мощь git diff и сценариев bash, мы можем сделать этот процесс простым, воспроизводимым и пригодным для использования как в локальном, так и в облачном контексте.

Весь приведенный выше исходный код доступен на GitHub.

Я надеюсь, что эта статья помогла вам начать работу с Netflix Conductor с помощью Elasticsearch 7 и PostgreSQL.

Удачного кодирования!

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

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