Выходим Из Ада Зависимостей В Qlikview



Выходим из ада зависимостей в QlikView



ТЛ;ДР;

В статье описывается, как Apache Airflow был реализован для управления заданиями обновления отчетов, построенными на QlikView, в довольно большой реализации.

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

Википедия



Введение

Мы поговорим о событиях, произошедших весной 2018 года, когда я работал в отделе систем аналитики компании «БИА-Технологии».

Мы занимались внедрением и поддержкой системы отчетности и аналитики QlikView в группе компаний «Бизнес Линии».

Хотя Qlik называет свой продукт QlikSense своим флагманом, QlikView, теперь версия 12.4, еще не сдалась окончательно и продолжает использоваться заказчиками и поддерживаться вендором.

Надеюсь, что этот эпизод из истории нашего внедрения будет вам интересен.



Немного теории

Основным артефактом в QlikView является так называемое «приложение» — это файл с расширением «QVW» и содержащий модель (по сути набор таблиц данных), визуальный интерфейс для анализа этих данных и скрипт в ней.

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

Модель данных в QlikView

Выходим из ада зависимостей в QlikView

Редактор сценариев

Выходим из ада зависимостей в QlikView

Вид интерфейса для анализа данных

Выходим из ада зависимостей в QlikView

Кстати, эти файлы также могут быть источником данных для других файлов этого формата.

Это решение «три в одном» весьма удобно, особенно если у вас настольная версия QV. Файлами легко делиться и с ними удобно работать.

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

Если вы хотите работать со свежими данными, то нажимаете кнопку «Обновить», ЭТЛ -script из того же файла, и в вашем отчете будет самая актуальная на данный момент информация.

Серверная версия QV работает с этими QVW-файлами так же, как и настольная версия: она загружает данные из своих моделей в оперативную память, и позволяет удаленным клиентам работать с этими данными, а для обновления используются те же скрипты.

По разным сервисам распределен только функционал обновления данных и предоставления доступа к ним.

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

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

В Qlik утверждают, что построенное таким образом решение способно полностью заменить корпоративное хранилище данных (EDW), и в некотором смысле это недалеко от истины.

С помощью QlikView вы можете собирать данные из разных источников и строить аналог QCD, используя файлы QVD. Но вы должны понимать, что построив все на QlikView, вы будете очень жестко привязаны к этому вендору, и ваши возможности, например, по экспорту этих данных, будут очень ограничены.

Кстати, у Qlik есть свой продукт для организации рассылок — NPrinting, и он востребован, видимо, не в последнюю очередь потому, что организует рассылки с помощью стороннего сервиса, например ССРС Работа с данными, хранящимися в QlikView, представляет собой необычайную задачу.

Опишу основные сервисы, которые используются в серверной версии QlikView:

  • Чтобы конечный пользователь мог анализировать данные, используется сервис QlikView Server (QVS).

    Он загружает файлы .

    QVW с диска в оперативную память и предоставляет интерфейс для работы с этими данными.

  • Отчеты обновляются службой распространения QlikView (QDS).

    Если вы не против потратить тысячи евро на лицензию издателя для него, то он превращается в Reload Engine, который поставляется в комплекте с сервером QlikView и имеет ограниченную функциональность: он работает только на том же оборудовании, что и QVS, и обновляет файлы отчетов «на месте», без возможности, например, распределять обновленные файлы по разным серверам, если их у вас несколько.

    Это, кстати, потенциальный источник проблем, ведь если при записи обновленного файла на диск этот файл в этот момент читается сервером QlikView, то возникнет конфликт и отчет не обновится.

  • Для администрирования всего этого объекта в Click предусмотрена отдельная служба под названием QlikView Management Service (QMS) — она также поставляется с сервером.

  • Служба лицензий, соединитель служб каталогов, веб-сервер — вспомогательные службы
Изображение серверной архитектуры с сайта Qlik

Выходим из ада зависимостей в QlikView



Что у нас было

В нашем случае у нас есть корпоративное хранилище данных, построенное на MS SQL, но нам еще пришлось построить ETL на QlikView для многоуровневой подготовки данных для отчетности.

Многоуровневость (или многослойность) проявляется в том, что некоторые файлы .

QVW не являются самостоятельными отчетами, а лишь подготавливают данные для других.

У таких файлов отсутствует визуальный интерфейс, а также модель данных.

Они состоят только из сценария, который извлекает, преобразует и сохраняет данные в файлы QVD. Основные требования к процессу обновления:

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

  • Чтобы с утра обеспечить бизнес-аналитиков и менеджеров актуальной информацией за вчерашний день, у нас есть окно обновления отчетности с полуночи до 8-9 утра, когда начинается рабочий день офисных сотрудников.

    Еще одним ограничением является то, что некоторые данные для отчетности доступны нам не с полуночи, а примерно с 4 утра, когда они формируются и загружаются в ККД другими сервисами, обрабатывающими результаты деятельности предприятия за вчерашний день.

В QMS есть возможность задавать расписание обновлений и зависимости файлов, но, к сожалению, этот функционал достаточно ограничен.

Например, мы можем установить зависимость только на один файл (по крайней мере, в случае с Reload Engine, который у нас был.

Для Publisher есть аналогичное ограничение, как там написано) русбарон в комментариях к статье нет).

Интерфейс QMS выглядит примерно так:

Выходим из ада зависимостей в QlikView

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

Также в QMS у нас нет возможности устанавливать приоритеты обновления отчетов.

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

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

Когда в нашей системе было мало приложений, это работало отлично.

Но потом, в ходе эксплуатации, их число превысило несколько десятков, и мы начали сталкиваться с проблемами.

  • Процесс обновления отчетности растянулся на все доступное нам окно и пытался выбраться дальше.

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

    , и т. д. .

    То есть продолжительность обновления конкретного приложения варьируется, и иногда существенно.

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

    Чем длиннее цепочка заявок, чем больше интервалов между ними, тем дольше занимает весь процесс.

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

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

  • Падения обновлений отчетности участились.

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

    А из-за того, что в стандартном планировщике невозможно было учесть все зависимости для большого количества файлов, такие моменты возникали всё чаще.

  • Участились инциденты с проблемой необновленных данных Все чаще возникали ситуации, когда задачи выполнялись не в том порядке.

    А затем приложение-потребитель брало данные из файла, который еще не был обновлен приложением-провайдером.

    В результате конечный пользователь увидел в отчете нерелевантную информацию.

  • Сбой одного отчета остановил процесс обновления большого количества других отчетов.

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

    Некоторые приложения, оказавшиеся достаточно тяжелыми, перелопачивают данные объемом около миллиарда строк, занимая почти всю доступную на сервере память.

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

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

    Но нам было бы полезно, если бы некоторые из этих отмененных заявок все же выполнялись.

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

    Отчет упал? Мы переносим его на другое время в расписании.

    Или мы делаем это зависимым от другого отчета.

    Проблема снова на следующий день? Приступим к манипуляциям снова.

В итоге, когда в нашей системе отчетности QlikView стало почти сотня приложений, мы поняли, что так продолжаться не может и начали искать системное решение этой проблемы.

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

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



Что мы наделали

Раз нативный сервис от QlikView не справляется самостоятельно, значит, надо ему помочь.

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

Для решения наших задач есть возможности интеграции QlikView и сторонних сервисов: в QMS есть API службы управления QlikView , с помощью которого мы можем многое сделать.

В том числе вытягивание на выполнение задачи через механизм EDX (Event Driven Execution).

Чтобы задача запускалась таким способом, в интерфейсе QMS приложения необходимо установить соответствующий флажок.

Будучи настоящими разработчиками, и видя «фатальные недостатки» во всех альтернативных решениях, мы, конечно же, задумались над внедрением системы управления задачами самостоятельно, тем более, что у нас уже был опыт реализации подобного примитивного планировщика для управления задачами NPrinting. Но благоразумие взяло верх, и в процессе изучения Интернета выяснилось, что существует такой класс программного обеспечения — Системы управления рабочими процессами.

После непродолжительного выбора подходящего для нас варианта из представителей данного семейства программного обеспечения мы решили попробовать реализовать Апач воздушный поток .

Airflow — достаточно зрелая система, очень удобная для создания потока задач и контроля процесса их выполнения.

У него замечательный, на мой взгляд, интерфейс и отличный функционал:

Выходим из ада зависимостей в QlikView



Как мы это сделали

Тестовая реализация завершилась примерно за неделю — пара дней на установку и ознакомление с сервисом, пара дней на написание и отладку операторского коннектора.

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

Они выложены в открытом доступе, если что, здесь: -> Плагин Airflow — QlikView .

API QMS является асинхронным.

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

А операторы в Airflow синхронны — они должны работать до тех пор, пока задача не будет выполнена.

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

Для каждой задачи Airflow сохраняет журналы попыток запуска.

Наш оператор по завершении задачи (неважно, успешно она или нет) записывает в этот лог ссылку на файл с логами выполнения этой задачи в QlikView, и соответственно вы сможете быстро найти все концы при выяснении причин крушения.

Для функционала запуска задач по условиям в Airflow реализованы так называемые датчики.

Это операторы, которые успешно завершают свою работу при возникновении какого-либо события.

Например, мы используем этот подход для запуска обновления некоторых отчетов в определенное время: мы делаем обновление зависимым от успешного завершения работы датчика в назначенное время.

Кроме того, мы можем отследить событие появления нужных нам данных в источнике, проверив, например, состояние чекбокса, и начать импорт данных именно в тот момент, когда это станет возможным.

Поток выполнения задач в Airflow реализован направленным ациклическим графом (DAG), в котором узлы представляют задачи, а связи между узлами представляют собой зависимости задач друг от друга.

Например, в следующем примере задача «Приложение 7» зависит от задач «ETL_4» и «ETL_5».

А задача «ETL_3» зависит от задачи «TimeSensor_6_30» — датчика времени, который срабатывает в 6:30.

Выходим из ада зависимостей в QlikView

Описание зависимостей графа и дополнительных параметров задачи в нашем случае реализовано словарем Python.

  
   

tasksDict = { u'ETL_1.qvw': {}, u'ETL_2.qvw': { 'Pool': 'Heavy_ETL_pool', }, u'ETL_3.qvw': { 'StartTime': [6, 30]}, u'ETL_4.qvw': { 'Priority': -5, 'Dep': [ u'ETL_1.qvw', u'ETL_3.qvw', ]}, u'ETL_5.qvw': { 'Dep': [ u'ETL_2.qvw', ]}, u'Application_6.qvw': { 'Dep': [ u'ETL_1.qvw', u'ETL_5.qvw', ]}, u'Application_7.qvw': { 'Dep': [ u'ETL_4.qvw', u'ETL_5.qvw', ]}, }

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

В нашем случае зависимости между приложениями QlikView выявляются отдельным приложением путем анализа кода их скриптов.

Объединив результат работы этого приложения и каталога с заданными вручную настройками для тех задач, которые в нем нуждаются (расписание работы, пул, в котором должна выполняться задача, приоритет), мы получаем итоговый DAG. И таким образом, после добавления нового отчета в репозиторий, он автоматически добавляется в DAG с учетом всех зависимостей.

Сейчас мы используем три пула задач: пул для обычных задач (5 одновременных задач), пул для тяжелых задач (1 задача) и пул для датчиков (100 задач).

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

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



Что мы имеем в итоге?

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



from datetime import datetime, timedelta from airflow import DAG from airflow.sensors.time_delta_sensor import TimeDeltaSensor from airflow.contrib.operators.qds_operator import QDSReloadApplicationOperator default_args = { 'owner': 'airflow', 'depends_on_past': False, 'start_date': datetime(2018, 1, 19), 'email': ['[email protected]'], 'email_on_failure': True, 'email_on_retry': False, 'retries': 0, 'retry_delay': timedelta(minutes=5), 'pool': 'default_pool', } dag = DAG('example_qds_operator', description='Reload applications at QlikView Distribution Service', catchup=False, schedule_interval='0 21 * * 5', default_args=default_args) tasksDict = { u'ETL_1.qvw': {}, u'ETL_2.qvw': { 'Pool': 'Heavy_ETL_pool', }, u'ETL_3.qvw': { 'StartTime': [6, 30]}, u'ETL_4.qvw': { 'Priority': -5, 'Dep': [ u'ETL_1.qvw', u'ETL_3.qvw', ]}, u'ETL_5.qvw': { 'Dep': [ u'ETL_2.qvw', ]}, u'Application_6.qvw': { 'Dep': [ u'ETL_1.qvw', u'ETL_5.qvw', ]}, u'Application_7.qvw': { 'Dep': [ u'ETL_4.qvw', u'ETL_5.qvw', ]}, } airflowTasksDict = {} for task in tasksDict.keys(): task_id = task.replace(" ", "_").

replace("'", "").

replace("/", "_").

replace("(", "_").

replace(")", "_").

replace(",", "_").

replace(".

qvw", "").

replace("__", "_") AirflowTask = QDSReloadApplicationOperator(document_name=task, task_id=task_id, qv_conn_id='qv_connection', dag=dag) airflowTasksDict[task] = AirflowTask for task in tasksDict.keys(): if 'Dep' in tasksDict[task]: for dep in tasksDict[task]['Dep']: airflowTasksDict[task].

set_upstream(airflowTasksDict[dep]) if 'Pool' in tasksDict[task]: airflowTasksDict[task].

pool = tasksDict[task]['Pool'] if 'Priority' in tasksDict[task]: airflowTasksDict[task].

priority_weight = tasksDict[task]['Priority'] if 'StartTime' in tasksDict[task]: hour = tasksDict[task]['StartTime'][0] minute = tasksDict[task]['StartTime'][1] sensorTime = timedelta(hours=hour, minutes=minute) sensorTaskID = u'TimeSensor_{}_{}'.

format(hour, minute) if sensorTaskID not in airflowTasksDict: SensorTask = TimeDeltaSensor(delta=sensorTime, task_id=sensorTaskID, pool='Sensors', dag=dag) airflowTasksDict[sensorTaskID] = SensorTask airflowTasksDict[task].

set_upstream(airflowTasksDict[sensorTaskID]) if __name__ == '__main__': dag.clear(reset_dag_runs=True) dag.run()

Вот как теперь выглядит график, согласно которому Airflow ежедневно обновляет отчеты QlikView:

Выходим из ада зависимостей в QlikView

Airflow избавил вас от головной боли, связанной с управлением задачами обновления.

Теперь мы имеем полный контроль над этим процессом.

Поскольку серверу не приходится простаивать из-за редкого расписания задач, общее время цикла обновления было сокращено.

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

.

В случае возникновения проблем Airflow может предпринять несколько попыток перезапустить невыполненное задание.

Количество необновленных к утру отчетов сократилось почти до нуля.

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

Тяжелые задачи выполняются в отдельном пуле, ширина которого равна 1 задаче.

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

Имеем возможность организовать полное и частичное интеграционное тестирование отчетности.

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

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

Также такое тестирование сейчас проводится перед переносом изменений в боевую обстановку.

Airflow формирует довольно полезную отчетность по статистике выполнения задач, и мы можем отслеживать динамику роста длительности задач, а также получать другие отчеты, например, диаграмму Ганта:

Выходим из ада зависимостей в QlikView

У нас боевой Airflow работает на виртуальной машине с двумя ядрами и 4 Гб оперативной памяти, и этого вполне достаточно для бесперебойной работы сервиса.

В целом, я думаю, мы проделали хорошую работу по решению проблемы обновления отчетов QlikView, и Airflow нам очень помог.



Выходим из ада зависимостей в QlikView

Теги: #python #Программное обеспечение #Анализ и проектирование систем #Визуализация данных #Инженерия данных #airflow #qlikview #qlikview #QlikView #борьба с хаосом

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.