Eventnative — Простой Инструмент Для Записи Потока Событий В Clickhouse

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

СобытиеРодной — это проект с открытым исходным кодом, разработанный командой Jitsu, который упрощает сбор данных о событиях.

EventNative поддерживает несколько хранилищ данных и Кликхаус - один из них.

Эта статья покажет вам, как настроить EventNative с помощью ClickHouse, а также даст советы по работе и повышению производительности и надежности.

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

Ситуация может стать особенно сложной, если в одной производственной среде работают разные версии одного и того же приложения (например, разные версии приложения iOS).

Архитектура EventNative максимально эффективна и надежна.

Он состоит из легковесного HTTP-сервера, который получает поток событий (состоящий из объектов JSON) и буферизует его на локальный диск.

Отдельный поток приложения обрабатывает этот буфер, сопоставляя объекты JSON с таблицами в ClickHouse, настраивая схему и сохраняя данные.



Быстрый запуск ClickHouse и EventNative

В этом разделе мы поговорим об установке узла с ClickHouse и EventNative с использованием официальных образов Docker. Обратите внимание, что здесь мы рассматриваем настройку среды разработки.

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

1. Загрузите образы Docker.

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
   

docker pull ksense/eventnative:latest && docker pull yandex/clickhouse-server:latest

2. Запустите ClickHouse

mkdir .

/clickhouse_data && docker run --name clickhouse-test -p 8123:8123 -v $PWD/clickhouse_data:/var/lib/clickhouse yandex/clickhouse-server

3. Настройка EventNative Добавьте следующий текст в

.

/eventnative.yaml



server: auth: - server_secret: 'ia7i92rqp3mh' # access token. We will need it later for sending events through HTTP API destinations: clickhouse: mode: stream clickhouse: dsns: - " http://default:@host.docker.internal:8123Эread_timeout=5m&timeout=5m " db: default data_layout: mappings: fields: - src: /field_1/sub_field_1 action: remove - src: /field_2/sub_field_1 dst: /field_10/sub_field_1 action: move - src: /field_3/sub_field_1/sub_sub_field_1 dst: /field_20 action: move type: DateTime - dst: /constant_field action: constant value: 1000

Также создайте каталог для логов:

mkdir .

/eventnative-logs

4. Запустите EventNative

docker run -d -t --name eventnative-test -p 8001:8001 \ -v $PWD/eventnative.yaml:/home/eventnative/app/res/eventnative.yaml \ -v $PWD/eventnative-logs:/home/eventnative/logs/events/ ksense/eventnative:latest

5. Отправьте тестовое событие и проверьте, что оно зарегистрировано в ClickHouse. Добавьте следующий объект в

.

/api.json

:

{ "eventn_ctx": { "event_id": "19b9907d-e814-42d8-a16d-c5da51e01531" }, "field_1": { "sub_field_1": "text1", "sub_field_2": 100 }, "field_2": "text2", "field_3": { "sub_field_1": { "sub_sub_field_1": "2020-09-25T12:38:27" } } }

Выполните следующую команду:

curl -X POST -H "Content-Type: application/json" -d @.

/api.json \ ' http://localhost:8001/api/v1/s2s/eventЭtoken=ia7i92rqp3mh '



echo 'SELECT * FROM events;' | curl ' http://localhost:8123/ ' --data-binary @-

Вы увидите одно событие в базе данных.

Тест сработал! 6. Тестирование буферизации событий Одной из основных функций EventNative является буферизация.

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

Если база данных (в нашем случае ClickHouse) недоступна, никакие данные не будут потеряны.

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

Давайте проверим эту функцию: Добавьте следующий JSON в

.

/api2.json

:

{ "eventn_ctx": { "event_id": "4748c7bb-50d4-43a7-91b4-21a5bcccb12e" }, "field_1": { "sub_field_1": "text1", "sub_field_2": 100 }, "field_2": "text2", "field_3": { "sub_field_1": { "sub_sub_field_1": "2020-09-25T12:38:27" } } }

Остановить ClickHouse

docker stop clickhouse-test

Отправить событие

curl -X POST -H "Content-Type: application/json" -d @.

/api2.json ' http://localhost:8001/api/v1/s2s/eventЭtoken=ia7i92rqp3mh '

Убедитесь, что ClickHouse действительно не работает

echo 'SELECT * FROM events;' | curl ' http://localhost:8123/ ' --data-binary @-

Запустите ClickHouse еще раз.



docker start clickhouse-test

Подождите 60 секунд и убедитесь, что событие не потеряно.



echo 'SELECT * FROM events;' | curl ' http://localhost:8123/ ' --data-binary @-



Управление схемой с помощью EventNative и ClickHouse

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

EventNative позаботится об этом автоматически! Каждое поле объекта JSON будет сопоставлено с полем SQL. Если поле отсутствует, оно будет автоматически создано в базе данных ClickHouse. Это особенно полезно, если одна команда разработчиков работает над структурой событий, а другая — над ClickHouse. Вот пример: фронтенд-разработчик может начать отправлять очень простые данные для отслеживания просмотров страниц продукта (идентификатор продукта и цена), а затем добавить более сложные поля (валюта и изображения).

Потому что они могут пригодиться.

Пример: JSON с событием

{ "product_id": "1e48fb70-ef12-4ea9-ab10-fd0b910c49ce", "product_price": 399.99, "price_currency": "USD", "product_type": "supplies", "product_release_start": "2020-09-25T12:38:27", "images": { "main": "picture1", "sub": "picture2" } }

Автоматически создаваемая структура таблицы:

"product_id" String, "product_price" Float64, "price_currency" String, "product_type" String, "product_release_start" String, "images_main" String, "images_sub" String

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

Проблема в том, что Поля, допускающие значение NULL, влияют на производительность .

Но если нужны значения Null, вы можете настроить список полей:

nullable_fields: ['product_id', 'product_price', 'price_currency']

(Смотреть полное описание конфигурации сопоставления )

Подробнее о конфигурации сопоставления

Изменяя настройки, EventNative может применять определенные преобразования к входящим объектам JSON, например:
  • Удалить поля
  • Переименование полей (включая перемещение поля на другой узел)
  • Явно определите тип поля
  • Замените константу
Пример

- src: /field_1/sub_field_1 action: remove - src: /field_2/sub_field_1 dst: /field_10/sub_field_1 action: move - src: /field_3/sub_field_1/sub_sub_field_1 dst: /field_20 action: move type: DateTime - dst: /constant_field action: constant value: 1000

Результатом применения правил является следующий JSON

{ "eventn_ctx": { "event_id": "19b9907d-e814-42d8-a16d-c5da51e01530" }, "field_1": { "sub_field_1": "text1", "sub_field_2": 100 }, "field_2": "text2", "field_3": { "sub_field_1": { "sub_sub_field_1": "2020-09-25T12:38:27" } } }

Превратится в такую запись в базе данных

{ "eventn_ctx_eventn_id": "19b9907d-e814-42d8-a16d-c5da51e01530", "field_1_sub_field_1": "text1", "field_1_sub_field_2": 100, "field_2": "text2", "field_3_sub_field_1_sub_sub_field_1": "2020-09-25T12:38:27.763000Z", "constant_field": 1000 }

Полное описание этой функции вы можете изучить в документации

Советы по продуктивности

ЗаменаMergeTree (или ReplicationReplacingMergeTree) — лучший движок для данных, сгенерированных EventNative, и вот почему:
  • Обычно данные, сгенерированные EventNative, используются в запросах с агрегатными функциями (например, при подсчете количества событий, удовлетворяющих некоторому условию, за заданный период времени).

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

  • ЗаменаMergeTree (в отличие от MergeTree) имеет приятный побочный эффект — дедупликацию данных.

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

    Иногда их приходится переписывать.

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

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

Если целевая таблица отсутствует, EventNative создаст таблицу с помощью ReplacingMergeTree или ReplicationReplacingMergeTree (если размер кластера больше 1).

Однако этот механизм можно настроить вручную.

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

Теги: #открытый исходный код #Администрирование баз данных #Большие данные #Инжиниринг данных #clickhouse #EventNative

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