Будучи распределенным ETL/ELT-инструментом потоковой передачи данных, Apache NiFi имеет соответствующие средства, которые обеспечивают взаимодействия между разными узлами кластера. Одним из них является протокол Site-to-Site (S2S), с которым мы познакомимся далее.
Что такое протокол S2S
При отправке данных из одного экземпляра NiFi в другой можно использовать множество различных протоколов, наиболее предпочтительным из которых является Site-to-Site (S2S). Он часто используется в VPN-соединениях. В NiFi этот протокол упрощает безопасную и эффективную передачу данных между разными узлами в одном экземпляре NiFi или приложении-продюсере на узлы в другом экземпляре NiFi или приложении-потребителе. Использование Site-to-Site дает следующие преимущества:
- Простота настройки — после ввода URL-адресов удаленного экземпляра доступные порты (конечные точки) автоматически обнаруживаются и отображаются в раскрывающемся списке;
- Безопасность – S2S дополнительно использует сертификаты для шифрования данных и обеспечения аутентификации и авторизации. Каждый порт можно настроить так, чтобы он разрешал доступ только определенным пользователям, и только эти пользователи смогут видеть, что порт вообще существует;
- Масштабируемость — по мере изменения узлов в удаленном кластере эти изменения автоматически обнаруживаются, и данные распределяются по всем узлам в кластере;
- Эффективность – S2S позволяет отправлять пакеты FlowFiles одновременно, чтобы избежать накладных расходов на установление соединений и выполнение нескольких запросов туда и обратно между одноранговыми узлами;
- Надежность — контрольные суммы автоматически создаются отправителем и получателем и сравниваются после передачи данных, чтобы гарантировать отсутствие искажений. Если контрольные суммы не совпадают, транзакция будет просто отменена и повторена попытка.
- Автоматическая балансировка нагрузки – когда узлы подключаются к сети или выходят из удаленного кластера, или нагрузка на узел становится больше или меньше, объем данных, направляемых на этот узел, будет автоматически корректироваться.
- Поддержка атрибутов FlowFile, что полезно, когда весь контекст и обогащение, которые были определены одним экземпляром NiFi, перемещаются вместе с данными, упрощая маршрутизацию данных и позволяя пользователям легко проверять данные.
- Адаптивность — при установке соединения с удаленным экземпляром NiFi, выполняет рукопожатие, чтобы согласовать, какая версия протокола Site-to-Site будет использоваться. Это позволяет добавлять новые возможности, сохраняя при этом обратную совместимость со всеми старыми экземплярами. Кроме того, если в протоколе когда-либо обнаруживается уязвимость или недостаток, это позволяет более новой версии NiFi запрещать связь через скомпрометированные версии протокола.
Поскольку протокол Site-to-Site передает данные между двумя экземплярами NiFi, следует уточнить разделение интегрируемых сторон:
- экземпляр NiFi, инициирующий связь, называется экземпляром NiFi клиента Site-to-Site;
- экземпляр NiFi, принимающий запрос, является экземпляром сервера Site-to-Site.
Один и тот же экземпляр NiFi не может одновременно являться клиентом и и сервером в рамках одного соединения S2S. Важно понимать, какой экземпляр NiFi будет клиентом или сервером, чтобы спроектировать поток данных и соответствующим образом настроить каждый экземпляр. В зависимости от направления потока данных разные запросы работают на различных сторонах:
- Push — клиент отправляет данные в удаленную группу процессов, сервер получает их на входной порт;
- Pull — клиент получает данные из удаленной группы процессов, сервер отправляет данные через выходной порт.
Для связи с удаленным экземпляром NiFi через протокол S2S используется группа удаленных процессов, в которой задается URL-адрес удаленного экземпляра NiFi и порт. Группе удаленных процессов может потребоваться время (около минуты), чтобы определить доступные порты. Также в диалоговом окне создания или настройки группы удаленных процессов задается транспортный протокол, который будет использоваться для связи Site-to-Site.
По умолчанию для транспортного протокола установлено значение RAW, которое использует связь через веб-сокеты с использованием выделенного порта. Можно использовать транспортный протокол HTTP, что особенно полезно, если удаленный экземпляр NiFi находится в сети с ограниченным доступом, которая разрешает доступ только через HTTP(S) или доступна только с определенного прокси-сервера HTTP. Для доступа через прокси-сервер HTTP поддерживаются аутентификация BASIC и DIGEST. Впрочем, можно также использовать локальный сетевой интерфейс.
Если введенное значение недопустимо, группа удаленных процессов не сможет взаимодействовать с другими экземплярами NiFi. Чтобы клиентский экземпляр NiFi мог получать информацию с сервера, на стороне сервера необходимо добавить в политику глобального доступа возможность получать сведения о соединениях S2S. Это позволит одному экземпляру NiFi запрашивать у другого имя, описание, доступные одноранговые узлы кластера, статистику, а также доступные входные и выходные порты.
Познакомившись с протоколом S2S, далее рассмотрим, как именно он реализует взаимодействие между различными экземплярами Apache NiFi.
Как работает Site-to-Site в Apache NiFi
Site-to-Site требует одноранговой связи между клиентом и удаленным узлом NiFi. Например, если удаленный кластер NiFi имеет 3 узла, то клиентские запросы должны быть доступны для каждого из них. Если кластер планирует получать или передавать данные между клиентам S2S через Интернет или корпоративный брандмауэр, обратный прокси-сервер может быть развернут перед узлами кластера NiFi в качестве шлюза для маршрутизации клиентских запросов к вышестоящим узлам NiFi, чтобы уменьшить количество серверов и портов, которые должны быть открыты.
В такой среде ожидается, что к одному и тому же кластеру NiFi будут обращаться клиенты Site-to-Site в той же сети, например, отправляя FlowFiles для распределения нагрузки между узлами кластера. В этом случае клиентские запросы должны направляться непосредственно на узел, минуя обратный прокси-сервер. Для поддержки таких развертываний удаленные кластеры NiFi должны динамически отображать свои конечные точки Site-to-Site на основе контекстов клиентских запросов. Чтобы настроить представление одноранговых узлов сервера их клиентам, используются соответствующие свойства, сгруппированные по protocol и name:
- remote.route.{protocol}.{name}.when — логическое значение (true или false), которое определяет, следует ли использовать определение маршрутизации для этого имени;
- nifi.remote.route.{protocol}.{name}.hostname — имя хоста, которое будет представлено клиентам Site-to-Site для дальнейшего взаимодействия;
- nifi.remote.route.{protocol}.{name}.port — номер порта, который будет предоставлен клиентам Site-to-Site для дальнейшего взаимодействия;
- nifi.remote.route.{protocol}.{name}.secure — логическое значение (true или false), которое указывает, следует ли осуществлять доступ к удаленному узлу через защищенный протокол. По умолчанию это значение установлено в false.
Все эти свойства маршрутизации могут использовать язык выражений NiFi для вычисления целевого однорангового описания из контекста запроса. Например, с помощью переменной s2s.{source|target}.hostname можно задать хост источника, откуда пришел запрос, и исходную цель, а переменная s2s.{source|target}.port позволяет определить то же самое для портов. Однако, исходный порт задавать в этом случае нет смысла, поскольку им будет TCP-порт на стороне клиента.
В общем случае последовательность взаимодействия экземпляров NiFi по протоколу Site-to-Site выглядит следующим образом:
- Клиент инициирует протокол Site-to-Site, отправляя запрос HTTP(S) на указанный удаленный URL-адрес для получения информации об удаленном кластере Site-to-Site;
- Удаленный узел NiFi отвечает своими входными и выходными портами, а также номерами портов TCP для транспортных протоколов RAW и TCP;
- Клиент отправляет еще один запрос на получение удаленных одноранговых узлов, используя ранее полученный номер порта TCP. Из этого запроса для транспортного протокола RAW используется связь через веб-сокеты, а HTTP продолжает использовать HTTP (S);
- Удаленный узел NiFi отвечает списком доступных удаленных одноранговых узлов, содержащим имя хоста, порт, безопасность и рабочую нагрузку, такую как количество FlowFiles в очереди. С этого момента между клиентом и удаленным узлом осуществляется дальнейшая связь.
- Клиент решает, от какого партнера передавать данные, на основе информации о рабочей нагрузке;
- Клиент отправляет запрос на создание транзакции на удаленный узел NiFi;
- Удаленный узел принимает транзакцию;
- Данные отправляются целевому узлу, причем в пакетном режиме могут быть отправлены несколько пакетов данных;
- Когда больше нет данных для отправки или достигнут предел пакета, транзакция подтверждается на обоих концах путем вычисления хэша CRC32 отправленных данных;
- Наконец, транзакция фиксируется на обоих концах.
Если визуализировать это взаимодействие в виде UML-диаграммы последовательности, оно будет выглядеть так:
Эта диаграмма было получена с помощью следующего скрипта PlantUML:
@startuml actor Клиент participant "Удаленный узел NiFi" as NiFi Клиент -> NiFi: Отправить запрос HTTP(S) NiFi --> Клиент: Входные/выходные порты\nНомера портов TCP Клиент -> NiFi: Отправить запрос на получение\nудаленных одноранговых узлов\n(используя номер порта TCP) NiFi --> Клиент: Список доступных удаленных\nодноранговых узлов Клиент -> Клиент: Выбор партнера для передачи данных Клиент -> NiFi: Отправить запрос на создание\nтранзакции NiFi --> Клиент: Согласие на транзакцию loop пока есть данные Клиент -> NiFi: Отправить данные целевому узлу\n(в пакетном режиме) end loop NiFi --> NiFi: Вычислить хэш CRC32 NiFi --> Клиент: Подтверждение транзакции Клиент -> NiFi: Фиксировать транзакцию NiFi --> Клиент: Транзакция фиксирована @enduml
Поскольку протокол поддерживает веб-сокеты и HTTP(S) в качестве базового транспортного протокола, можно встроить прокси-сервер в связь S2S. Для передачи данных по протоколу Site-to-Site через обратные прокси-серверы пользователи всех интегрируемых систем должны иметь соответствующие политики для входных и выходных портов, позволяющие принимать и отправлять данные.
Большинство программ обратного прокси-сервера реализуют режим прокси-сервера HTTP и TCP. Для протокола NiFi RAW Site-to-Site требуются конфигурации прокси-сервера HTTP и TCP, а также необходимо открыть как минимум 2 порта. Протокол HTTP Site-to-Site может минимизировать необходимое количество открытых портов на обратном прокси-сервере до 1. Установка правильных заголовков HTTP на обратных прокси-серверах имеет решающее значение для правильной работы фреймворка, не только для маршрутизации запросов, но и для авторизации клиентских запросов.
Существует два типа методов сопоставления запросов с узлами фреймворка, которые можно применять на обратных прокси-серверах. Один из них — «Имя сервера для узла», а другой — «Номер порта для узла». С «Именем сервера на узел» один и тот же порт можно использовать для маршрутизации запросов к разным вышестоящим узлам NiFi на основе запрошенного имени сервера. Разрешение имен хостов должно быть настроено для сопоставления разных имен хостов с одним и тем же адресом обратного прокси-сервера, что можно сделать, добавив файл /etc/hosts или записи DNS-сервера. Кроме того, если клиенты для обратного прокси-сервера используют HTTPS, сертификат обратного прокси-сервера должен иметь подстановочное общее имя или SAN, чтобы к нему могли обращаться разные имена хостов. Если обратный прокси-сервер не поддерживает правила маршрутизации имени сервера, следует задать номер порта на узел, что потребует N открытых портов на обратном прокси-сервере для кластера NiFi, состоящего из N узлов.
Чтобы проиллюстрировать, как выглядят файлы конфигурации обратного прокси и самого фреймворка, рассмотрим пример, когда один клиент (Client1) не имеет прямого доступа к узлам NiFi и получает его через обратный прокси-сервер Nginx, а другой клиент (Client 2) имеет прямой доступ к узлам. Правило маршрутизации S2S при использовании протокола HTTP в качестве транспорта, определенное в файле конфигурации nifi.properties, выглядит так:
nifi.remote.route.http.example.when=${X-ProxyHost:contains('.example.com')} nifi.remote.route.http.example.hostname=${s2s.target.hostname}.example.com nifi.remote.route.http.example.port=443 nifi.remote.route.http.example.secure=true
А конфигурация обратного прокcи Nginx, заданная в файле nginx.conf, будет следующей:
http { upstream nifi_cluster { server nifi0:8443; server nifi1:8443; server nifi2:8443; } # If target node is not specified, use one from cluster. map $http_host $nifi { nifi0.example.com:443 "nifi0:8443"; nifi1.example.com:443 "nifi1:8443"; nifi2.example.com:443 "nifi2:8443"; default "nifi_cluster"; } resolver 127.0.0.1; server { listen 443 ssl; server_name ~^(.+\.example\.com)$; ssl_certificate /etc/nginx/nginx.crt; ssl_certificate_key /etc/nginx/nginx.key; proxy_ssl_certificate /etc/nginx/nginx.crt; proxy_ssl_certificate_key /etc/nginx/nginx.key; proxy_ssl_trusted_certificate /etc/nginx/nifi-cert.pem; location / { proxy_pass https://$nifi; proxy_set_header X-ProxyScheme https; proxy_set_header X-ProxyHost $1; proxy_set_header X-ProxyPort 443; proxy_set_header X-ProxyContextPath /; proxy_set_header X-ProxiedEntitiesChain <$ssl_client_s_dn>; } } }
О том, как передать системные метрики S2S-протокола во внешние системы мониторинга с помощью задач отчетности, читайте в нашей новой статье.
Узнайте больше про администрирование и использование Apache NiFi для построения эффективных ETL-конвейеров потоковой аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
Источники