Интеграция OpenTelemetry для сбора данных
Любое решение по мониторингу требует средства для сбора и экспорта логов и трассировок. Для этой цели ClickHouse рекомендует проект OpenTelemetry (OTel).
"OpenTelemetry - это фреймворк и набор инструментов для мониторинга, предназначенный для создания и управления телеметрическими данными, такими как трассировки, метрики и логи."
В отличие от ClickHouse или Prometheus, OpenTelemetry не является бэкендом для мониторинга, а сосредоточен на генерации, сборе, управлении и экспорте телеметрических данных. Хотя первоначальной целью OpenTelemetry было облегчить пользователям инструментирование своих приложений или систем с использованием специфичных для языка SDK, проект расширился, чтобы включать сбор логов через OpenTelemetry Collector - агент или прокси, который получает, обрабатывает и экспортирует телеметрические данные.
Компоненты, относящиеся к ClickHouse
OpenTelemetry состоит из множества компонентов. Помимо предоставления спецификации данных и API, стандартизированного протокола и соглашений о наименованиях для полей/столбцов, OTel предлагает две возможности, которые являются фундаментальными для построения решения по мониторингу с ClickHouse:
- OpenTelemetry Collector - это прокси, который получает, обрабатывает и экспортирует телеметрические данные. Решение на базе ClickHouse использует этот компонент как для сбора логов, так и для обработки событий перед пакетной вставкой.
- Языковые SDK, которые реализуют спецификацию, API и экспорт телеметрических данных. Эти SDK эффективно гарантируют, что трассировки записываются корректно в коде приложения, генерируя составные спаны и обеспечивая распространение контекста по сервисам через метаданные - таким образом формируя распределенные трассировки и обеспечивая корреляцию спанов. Эти SDK дополняются экосистемой, которая автоматически внедряет общие библиотеки и фреймворки, что означает, что пользователю не требуется изменять свой код, и он получает инструментирование "из коробки".
Решение по мониторингу на базе ClickHouse использует оба этих инструмента.
Дистрибутивы
OpenTelemetry collector имеет несколько дистрибутивов. Приемник filelog вместе с экспортером ClickHouse, необходимым для решения на базе ClickHouse, присутствует только в дистрибутиве OpenTelemetry Collector Contrib.
Этот дистрибутив содержит множество компонентов и позволяет пользователям экспериментировать с различными конфигурациями. Однако при развертывании в производственной среде рекомендуется ограничить коллектор только теми компонентами, которые необходимы для данной среды. Вот некоторые причины для этого:
- Уменьшение размера коллектора, что сокращает время развертывания коллектора.
- Повышение безопасности коллектора путем уменьшения доступной площади атаки.
Создание индивидуального коллектора можно осуществить с помощью OpenTelemetry Collector Builder.
Прием данных с OTel
Роли развертывания коллектора
Для сбора логов и вставки их в ClickHouse мы рекомендуем использовать OpenTelemetry Collector. OpenTelemetry Collector можно развернуть в двух основных ролях:
- Агент - экземплары агента собирают данные на краю сети, например, на серверах или на узлах Kubernetes, или получают события непосредственно от приложений, инструментированных с помощью OpenTelemetry SDK. В последнем случае экземпляр агента работает вместе с приложением или на том же хосте, что и приложение (например, в качестве sidecar или DaemonSet). Агенты могут отправлять свои данные непосредственно в ClickHouse или на экземпляр шлюза. В первом случае это называется шаблон развертывания агента.
- Шлюз - Экземпляры шлюза предоставляют отдельную службу (например, развертывание в Kubernetes), обычно на кластер, дата-центр или регион. Они получают события от приложений (или других коллекторов в качестве агентов) через единую точку доступа OTLP. Обычно развертывается набор экземпляров шлюза, с использованием готового балансировщика нагрузки для распределения нагрузки между ними. Если все агенты и приложения отправляют свои сигналы на эту единую точку доступа, это часто называется шаблоном развертывания шлюза.
Далее мы предполагаем простой коллектор-агент, который отправляет свои события непосредственно в ClickHouse. См. Масштабирование с использованием шлюзов для получения дополнительных сведений об использовании шлюзов и о том, когда они применимы.
Сбор логов
Основное преимущество использования коллектора заключается в том, что он позволяет вашим сервисам быстро выгружать данные, оставляя Collectoru заботиться о дополнительной обработке, такой как повторные попытки, пакетирование, шифрование или даже фильтрация конфиденциальных данных.
Коллектор использует термины приемник, процессор и экспортер для своих трех основных этапов обработки. Приемники используются для сбора данных и могут быть как pull, так и push-ориентированными. Процессоры предоставляют возможность выполнения преобразований и обогащения сообщений. Экспортеры отвечают за отправку данных в прикладную службу. Хотя эта служба может теоретически быть другим коллектором, мы предполагаем, что все данные отправляются непосредственно в ClickHouse для первоначального обсуждения ниже.

Мы рекомендуем пользователям ознакомиться с полным набором приемников, процессоров и экспортеров.
Коллектор предоставляет два основных приемника для сбора логов:
Через OTLP - В этом случае логи отправляются (пушатся) непосредственно в коллектор из OpenTelemetry SDK через протокол OTLP. Демо OpenTelemetry использует этот подход, при этом экспортеры OTLP для каждого языка предполагают локальную точку доступа коллектора. Коллектор в этом случае должен быть настроен с приемником OTLP — смотрите выше демо для конфигурации. Преимущество этого подхода заключается в том, что данные лога автоматически будут содержать Trace Ids, позволяя пользователям позже идентифицировать трассировки для конкретного лога и наоборот.

Этот подход требует от пользователей инструментировать свой код с помощью соответствующего языка SDK.
- Скрейпинг через приемник Filelog - Этот приемник отслеживает файлы на диске и формирует сообщения логов, отправляя их в ClickHouse. Этот приемник обрабатывает сложные задачи, такие как обнаружение мультилитейных сообщений, обработка ротации логов, контрольная точка для обеспечения надежности перезапуска и извлечение структуры. Этот приемник также может отслеживать логи контейнеров Docker и Kubernetes, которые можно развернуть как helm chart, извлекая структуру из этих логов и обогащая их деталями пода.

Большинство развертываний будет использовать комбинацию вышеуказанных приемников. Мы рекомендуем пользователям ознакомиться с документацией коллектора и понять основные концепции, а также структуру конфигурации и методы установки.
Структурированные против неструктурированных
Логи могут быть как структурированными, так и неструктурированными.
Структурированный лог будет использовать формат данных, такой как JSON, определяя метаданные, такие как http код и IP-адрес источника.
Неструктурированные логи, хотя также имеющие некоторую внутреннюю структуру, извлекаемую через регулярное выражение, будут представлять лог исключительно как строку.
Мы рекомендуем пользователям использовать структурированное логирование и логировать в JSON (т.е. ndjson), где это возможно. Это упростит последующую обработку логов, либо перед отправкой в ClickHouse с помощью процессоров коллектора, либо во время вставки с использованием материализованных представлений. Структурированные логи в конечном итоге сэкономят ресурсы для последующей обработки, снижающей необходимую производительность CPU в вашем решении на основе ClickHouse.
Пример
Для примера мы предоставляем структурированный (JSON) и неструктурированный набор данных логов, каждый примерно с 10 млн строк, доступных по следующим ссылкам:
Мы используем структурированный набор данных для примера ниже. Убедитесь, что этот файл загружен и распакован, чтобы воспроизвести приведенные ниже примеры.
Ниже представлена простая конфигурация для OTel Collector, которая считывает эти файлы на диске, используя приемник filelog, и выводит полученные сообщения на stdout. Мы используем оператор json_parser
, поскольку наши логи структурированы. Измените путь к файлу access-structured.log.
Приведенный ниже пример извлекает временную метку из лога. Для этого требуется использование оператора json_parser
, который преобразует всю строку лога в строку JSON, помещая результат в поле LogAttributes
. Это может быть вычислительно затратным и может быть выполнено более эффективно в ClickHouse - Извлечение структуры с помощью SQL. Эквивалентный неструктурированный пример, который использует regex_parser
для достижения этого, можно найти здесь.
Пользователи могут следовать официальным инструкциям для локальной установки коллектора. Важно убедиться, что инструкции изменены для использования дистрибуции contrib (которая содержит приемник filelog
), например, вместо otelcol_0.102.1_darwin_arm64.tar.gz
пользователи должны загрузить otelcol-contrib_0.102.1_darwin_arm64.tar.gz
. Релизы можно найти здесь.
После установки OTel Collector можно запустить с помощью следующих команд:
Предполагая использование структурированных логов, сообщения будут иметь следующий вид на выходе:
Выше представлено одно сообщение лога, созданное OTel collector. Мы будем импортировать эти же сообщения в ClickHouse в следующих разделах.
Полная схема логов, наряду с дополнительными колонками, которые могут быть присутствовать при использовании других приемников, хранится здесь. Мы настоятельно рекомендуем пользователям ознакомиться с этой схемой.
Ключевым моментом здесь является то, что сама строка лога хранится как строка в поле Body
, но JSON был автоматически извлечен в поле Attributes благодаря оператору json_parser
. Этот же оператор был использован для извлечения временной метки в соответствующий столбец Timestamp
. Для рекомендаций по обработке логов с OTel см. Обработка.
Операторы - это самая базовая единица обработки логов. Каждый оператор выполняет одну конкретную задачу, такую как чтение строк из файла или парсинг JSON из поля. Операторы затем связываются вместе в конвейере для достижения желаемого результата.
Приведенные выше сообщения не имеют полей TraceID
или SpanID
. Если они присутствуют, например, в случаях, когда пользователи реализуют распределенную трассировку, они могут быть извлечены из JSON с использованием тех же методов, показанных выше.
Для пользователей, которым нужно собирать локальные или Kubernetes файлы логов, мы рекомендуем ознакомиться с доступными параметрами конфигурации для приемника filelog и как обрабатываются смещения и парсинг многострочных логов.
Сбор логов Kubernetes
Для сбора логов Kubernetes мы рекомендуем документальное руководство OpenTelemetry. Рекомендуется использовать Kubernetes Attributes Processor для обогащения логов и метрик метаданными пода. Это может потенциально создать динамические метаданные, например, метки, хранящиеся в колонке ResourceAttributes
. ClickHouse в настоящее время использует тип Map(String, String)
для этой колонки. Смотрите Использование Maps и Извлечение из maps для получения дополнительных сведений о работе с этим типом и оптимизации.
Сбор трассировок
Для пользователей, желающих инструментировать свой код и собирать трассировки, мы рекомендуем следовать официальной документации OTel.
Для передачи событий в ClickHouse пользователям необходимо развернуть OTel collector для получения событий трассировки через протокол OTLP с помощью соответствующего приемника. Демонстрация OpenTelemetry предоставляет пример инструментирования каждого поддерживаемого языка и отправки событий на коллектор. Пример соответствующей конфигурации коллектора, который выводит события на stdout, представлен ниже:
Пример
Так как трассировки должны быть получены через OTLP, мы используем инструмент telemetrygen
для генерации данных трассировки. Следуйте инструкциям здесь для установки.
Следующая конфигурация получает события трассировки на приемнике OTLP, прежде чем отправить их на stdout.
Запустите эту конфигурацию через:
Отправьте события трассировки на коллектор через telemetrygen
:
Это приведет к выводимым сообщениям трассировки, похожим на приведенный ниже пример, на stdout:
Выше представлено одно сообщение трассировки, созданное OTel collector. Мы будем импортировать эти же сообщения в ClickHouse в следующих разделах.
Полная схема сообщений трассировки хранится здесь. Мы настоятельно рекомендуем пользователям ознакомиться с этой схемой.
Обработка - фильтрация, преобразование и обогащение
Как было показано в предыдущем примере установки временной метки для события лога, пользователи неизбежно захотят фильтровать, преобразовывать и обогащать сообщения событий. Это можно сделать с помощью нескольких возможностей OpenTelemetry:
-
Процессоры - Процессоры берут данные, собранные приемниками, и модифицируют или трансформируют их перед отправкой их экспортеру. Процессоры применяются в заданном порядке, как настроено в секции
processors
конфигурации коллектора. Эти процессоры являются необязательными, но минимальный набор обычно рекомендуется. При использовании OTel collector с ClickHouse мы рекомендуем ограничить число процессоров:- memory_limiter используется для предотвращения ситуаций, связанных с нехваткой памяти у коллектора. Смотрите Оценка ресурсов для рекомендаций.
- Любой процессор, который делает обогащение на основе контекста. Например, Kubernetes Attributes Processor позволяет автоматически устанавливать атрибуты ресурсов для спанов, метрик и логов с метаданными k8s, например, обогащая события идентификатором их источника пода.
- Tail или head sampling, если требуется для трассировок.
- Основная фильтрация - исключение событий, которые не нужны, если это нельзя сделать с помощью оператора (см. ниже).
- Пакетирование - необходимо при работе с ClickHouse, чтобы гарантировать, что данные отправляются пакетами. См. "Экспорт в ClickHouse".
-
Операторы - Операторы предоставляют самую базовую единицу обработки, доступную на приемнике. Поддерживается базовый парсинг, позволяющий устанавливать такие поля, как severity и timestamp. Поддерживается парсинг JSON и regex, а также фильтрация событий и базовые преобразования. Мы рекомендуем выполнять фильтрацию событий именно здесь.
Мы рекомендуем пользователям избегать чрезмерной обработки событий с использованием операторов или процессоров трансформации. Это может привести к значительным накладным расходам на память и CPU, особенно при парсинге JSON. Возможность выполнить всю обработку в ClickHouse во время вставки с использованием материализованных представлений и столбцов, за некоторыми исключениями, - в частности, контекстное обогащение, например, добавление метаданных k8s. Для получения дополнительных сведений см. Извлечение структуры с помощью SQL.
Если обработка выполняется с использованием OTel collector, мы рекомендуем выполнять преобразования на экземплярах шлюза и минимизировать любые действия на экземплярах агентов. Это обеспечит минимальную нагрузку на ресурсы, необходимую агентам на границе, работающим на серверах. Обычно мы видим, что пользователи выполняют только фильтрацию (чтобы минимизировать ненужное использование сети), установку временной метки (через операторов) и обогащение, которое требует контекста в агенте. Например, если экземпляры шлюза находятся в другом кластере Kubernetes, то обогащение k8s должно произойти в агенте.
Пример
Следующая конфигурация показывает сбор неструктурированного файла логов. Обратите внимание на использование операторов для извлечения структуры из строк логов (regex_parser
) и фильтрации событий, наряду с процессором для пакетирования событий и ограничения потребления памяти.
config-unstructured-logs-with-processor.yaml
Экспорт в ClickHouse
Экспортеры отправляют данные в один или несколько бэкендов или пунктов назначения. Экспортеры могут быть pull или push-ориентированными. Для отправки событий в ClickHouse пользователям необходимо использовать push-ориентированный экспортер ClickHouse.
Экспортер ClickHouse является частью OpenTelemetry Collector Contrib, а не основной дистрибуции. Пользователи могут либо использовать дистрибуцию contrib, либо создать собственный коллектор.
Полный файл конфигурации показан ниже.
Обратите внимание на следующие ключевые настройки:
- pipelines - В приведенной выше конфигурации подчеркивается использование конвейеров, состоящих из набора приемников, процессоров и экспортеров, по одному для логов и трассировок.
- endpoint - Связь с ClickHouse настраивается через параметр
endpoint
. Строка соединенияtcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1
обеспечивает связь по TCP. Если пользователи предпочитают HTTP по причинам переключения трафика, измените эту строку подключения, как описано здесь. Полные детали соединения с возможностью указания имени пользователя и пароля в этой строке соединения описаны здесь.
Важно: Обратите внимание, что приведенная выше строка подключения включает как сжатие (lz4), так и асинхронные вставки. Мы рекомендуем всегда включать оба. Смотрите Пакетирование для получения дополнительных сведений об асинхронных вставках. Сжатие всегда должно быть указано и по умолчанию не будет активировано на более старых версиях экспортера.
- ttl - значение здесь определяет, как долго данные будут храниться. Дополнительные сведения смотрите в разделе "Управление данными". Это должно быть указано как единица времени в часах, например, 72h. Мы отключаем TTL в примере ниже, так как наши данные датированы 2019 годом и будут сразу удалены ClickHouse при вставке.
- traces_table_name и logs_table_name - определяет имя таблицы логов и трассировок.
- create_schema - определяет, создаются ли таблицы со схемами по умолчанию при запуске. По умолчанию true для начала работы. Пользователи должны установить его в false и определить свою собственную схему.
- database - целевая база данных.
- retry_on_failure - параметры для определения того, следует ли повторять неудачные пакеты.
- batch - процессор пакетирования обеспечивает отправку событий пакетами. Мы рекомендуем значение около 5000 с таймаутом в 5 секунд. То, что из этих значений достигнет первого, инициирует пакет, который будет сброшен экспортёру. Уменьшение этих значений приведет к меньшей задержке в конвейере с данными, доступными для запроса быстрее, за счет большего количества соединений и пакетов, отправленных в ClickHouse. Это не рекомендуется, если пользователи не используют асинхронные вставки, так как это может вызвать проблемы с слишком большим количеством частей в ClickHouse. Напротив, если пользователи используют асинхронные вставки, доступность данных для запроса также будет зависеть от настроек асинхронного вставки - хотя данные по-прежнему будут сбрасываться из соединителя быстрее. Смотрите Пакетирование для получения дополнительных сведений.
- sending_queue - контролирует размер очереди отправки. Каждый элемент в очереди содержит пакет. Если эта очередь превышена, например, из-за недоступности ClickHouse, но события продолжают поступать, пакеты будут отброшены.
Предполагая, что пользователи распаковали структурированный файл лога и имеют локальный экземпляр ClickHouse, работающий (с подачей доступа по умолчанию), пользователи могут запустить эту конфигурацию с помощью команды:
Чтобы отправить данные трассировки в этот коллектор, выполните следующую команду с использованием инструмента telemetrygen
:
После запуска подтвердите наличие событий журнала простым запросом:
Схема 'из коробки'
По умолчанию экспортер ClickHouse создает целевую таблицу логов для как логов, так и трассировок. Это можно отключить через настройку create_schema
. Более того, имена как таблицы логов, так и трассировок могут быть изменены с их значений по умолчанию otel_logs
и otel_traces
через вышеуказанные настройки.
В нижеприведенных схемах мы предполагаем, что TTL был включен как 72 часа.
Схема по умолчанию для логов представлена ниже (otelcol-contrib v0.102.1
):
Столбцы здесь соответствуют официальной спецификации OTel для логов, задокументированной здесь.
Несколько важных заметок по этой схеме:
- По умолчанию таблица разбита по дате с помощью
PARTITION BY toDate(Timestamp)
. Это делает эффективным удаление данных, которые истекли. - TTL устанавливается с помощью
TTL toDateTime(Timestamp) + toIntervalDay(3)
и соответствует значению, установленному в конфигурации коллектора.ttl_only_drop_parts=1
означает, что удаляются только целые части, когда все содержащиеся строки истекли. Это более эффективно, чем удаление строк внутри частей, что связано с дорогим удалением. Мы рекомендуем всегда устанавливать это значение. См. Управление данными с TTL для получения более подробной информации. - Таблица использует классический
MergeTree
движок. Это рекомендуется для логов и трассировок и не должно требовать изменений. - Таблица отсортирована по
ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId)
. Это означает, что запросы будут оптимизированы для фильтров поServiceName
,SeverityText
,Timestamp
иTraceId
- более ранние столбцы в списке будут фильтроваться быстрее, чем более поздние. Например, фильтрация поServiceName
будет значительно быстрее, чем фильтрация поTraceId
. Пользователи должны изменить эту сортировку в соответствии с ожидаемыми паттернами доступа - см. Выбор первичного ключа. - Вышеприведенная схема применяет
ZSTD(1)
к столбцам. Это обеспечивает наилучшее сжатие для логов. Пользователи могут увеличить уровень сжатия ZSTD (выше значения по умолчанию 1) для улучшения сжатия, хотя это редко бывает полезно. Увеличение этого значения приведет к большему накладному времени CPU во время вставки (во время сжатия), хотя декомпрессия (и, таким образом, запросы) должны оставаться сопоставимыми. См. здесь для получения дальнейших деталей. Дополнительное дельта-кодирование применяется к Timestamp с целью уменьшения его размера на диске. - Обратите внимание, что
ResourceAttributes
,LogAttributes
иScopeAttributes
являются ассоциативными массивами. Пользователи должны ознакомиться с различиями между ними. Для получения информации о том, как получить доступ к этим ассоциативным массивам и оптимизировать доступ к ключам внутри них, см. Использование ассоциативных массивов. - Большинство других типов здесь, например,
ServiceName
как LowCardinality, оптимизированы. Обратите внимание, чтоBody
, который является JSON в наших примерах логов, хранится как строка. - Фильтры Блума применяются к ключам и значениям ассоциативных массивов, а также к столбцу
Body
. Это направлено на улучшение времени выполнения запросов для запросов, обращающихся к этим столбцам, но обычно не требуется. См. Вторичные/индексы пропуска данных.
Снова, это будет коррелировать со столбцами, соответствующими официальной спецификации OTel для трассировок, задокументированной здесь. Схема здесь применяет многие из тех же настроек, что и вышеуказанная схема логов с дополнительными столбцами Link, специфичными для спанов.
Мы рекомендуем пользователям отключить автоматическое создание схем и создать свои таблицы вручную. Это позволяет изменить первичные и вторичные ключи, а также дать возможность вводить дополнительные столбцы для оптимизации производительности запросов. Для получения дальнейших деталей см. Проектирование схем.
Оптимизация вставок
Для достижения высокой производительности вставки при получении строгих гарантий консистентности пользователи должны следовать простым правилам при вставке данных наблюдаемости в ClickHouse через коллектор. При правильной конфигурации коллектора OTel следующие правила должны быть простыми в исполнении. Это также помогает избежать распространенных проблем, с которыми сталкиваются пользователи в первый раз, используя ClickHouse.
Пакетирование
По умолчанию каждая вставка, отправляемая в ClickHouse, приводит к немедленному созданию части хранения, содержащей данные из вставки вместе с другой метаинформацией, которую необходимо хранить. Таким образом, отправка меньшего количества вставок, каждая из которых содержит больше данных, по сравнению с отправкой большего количества вставок, каждая из которых содержит меньше данных, сократит необходимое число записей. Мы рекомендуем вставлять данные в довольно больших пакетах, как минимум по 1000 строк за раз. Подробнее здесь.
По умолчанию вставки в ClickHouse являются синхронными и идемпотентными, если идентичны. Для таблиц семейства движков merge tree ClickHouse по умолчанию автоматически удаляет дубликаты вставок. Это означает, что вставки являются устойчивыми к таким случаям:
- (1) Если узел, получающий данные, имеет проблемы, запрос вставки истечет по времени (или получит более конкретную ошибку) и не получит подтверждение.
- (2) Если данные были записаны узлом, но подтверждение не может быть возвращено отправителю запроса из-за сетевых перебоев, отправитель либо получит тайм-аут, либо сетевую ошибку.
С точки зрения коллектора (1) и (2) могут быть трудны для различения. Однако в обоих случаях неподтвержденная вставка может немедленно быть повторена. При условии, что повторно отправляемый запрос вставки содержит одни и те же данные в том же порядке, ClickHouse автоматически проигнорирует повторную вставку, если (неподтвержденная) оригинальная вставка прошла успешно.
Мы рекомендуем пользователям использовать пакетный процессор, показанный в предыдущих конфигурациях, чтобы удовлетворить вышеуказанные требования. Это гарантирует, что вставки отправляются как согласованные пакеты строк, удовлетворяющие вышеуказанным требованиям. Если ожидается, что коллектор будет иметь высокую пропускную способность (события в секунду), и как минимум 5000 событий могут быть отправлены в каждой вставке, это обычно единственное пакетирование, требуемое в конвейере. В этом случае коллектор будет сбрасывать пакеты перед истечением времени ожидания пакетного процессора timeout
, гарантируя, что задержка от конца до конца конвейера остается низкой, а пакеты имеют согласованный размер.
Используйте асинхронные вставки
Обычно пользователи вынуждены отправлять меньшие пакеты, когда пропускная способность коллектора низка, но при этом они все еще ожидают, что данные прибудут в ClickHouse с минимальной задержкой от начала до конца. В этом случае небольшие пакеты отправляются, когда истекает время ожидания пакетного процессора. Это может вызывать проблемы, и именно тогда требуются асинхронные вставки. Этот случай обычно возникает, когда коллекторы в роли агента настроены на отправку данных непосредственно в ClickHouse. Шлюзы, действуя как агрегаторы, могут облегчить эту проблему - см. Масштабирование с помощью шлюзов.
Если большие пакеты не могут быть гарантированы, пользователи могут делегировать пакетирование ClickHouse с использованием Асинхронных вставок. С асинхронными вставками данные сначала вставляются в буфер, а затем записываются в хранилище базы данных позже или асинхронно соответственно.

С включенными асинхронными вставками, когда ClickHouse ① получает запрос вставки, данные запроса ② немедленно записываются в буфер внутри памяти. Когда ③ происходит следующий сброс буфера, данные буфера сортируются и записываются как часть в хранилище базы данных. Обратите внимание, что данные не могут быть доступны для запросов до тех пор, пока они не будут сброшены в хранилище базы данных; сброс буфера настраивается.
Чтобы включить асинхронные вставки для коллектора, добавьте async_insert=1
в строку подключения. Мы рекомендуем пользователям использовать wait_for_async_insert=1
(по умолчанию) для получения гарантий доставки - см. здесь для получения дальнейших деталей.
Данные из асинхронной вставки вставляются после того, как буфер ClickHouse сброшен. Это происходит либо после превышения async_insert_max_data_size
, либо после async_insert_busy_timeout_ms
миллисекунд с момента первого запроса INSERT. Если async_insert_stale_timeout_ms
установлено в ненулевое значение, данные вставляются после async_insert_stale_timeout_ms миллисекунд
с момента последнего запроса. Пользователи могут настроить эти параметры для управления задержкой от начала до конца своего конвейера. Дополнительные настройки, которые могут быть использованы для настройки сброса буфера, задокументированы здесь. Обычно значения по умолчанию подходят.
В случаях, когда используется небольшое количество агентов с низкой пропускной способностью, но строгими требованиями к задержке от начала до конца, адаптивные асинхронные вставки могут быть полезны. Обычно они не применимы к случаям использования наблюдаемости с высокой пропускной способностью, как это видно с ClickHouse.
Наконец, предыдущее поведение удаления дубликатов, связанное с синхронными вставками в ClickHouse, не включено по умолчанию при использовании асинхронных вставок. Если это необходимо, смотрите настройку async_insert_deduplicate
.
Полные детали по настройке этой функции можно найти здесь, с более глубоким погружением здесь.
Архитектуры развертывания
При использовании коллектора OTel с ClickHouse возможно несколько архитектур развертывания. Ниже мы описываем каждую из них и когда она может быть применима.
Только агенты
В архитектуре только с агентами пользователи развертывают коллектор OTel как агентов на краю. Эти агенты получают трассировки от локальных приложений (например, как контейнер sidecar) и собирают логи с серверов и узлов Kubernetes. В этом режиме агенты отправляют свои данные непосредственно в ClickHouse.

Эта архитектура подходит для развертываний малого и среднего размера. Ее основное преимущество заключается в том, что она не требует дополнительного оборудования и сохраняет общий ресурсный след решения по наблюдаемости ClickHouse минимальным, с простым сопоставлением между приложениями и коллекторами.
Пользователи должны рассмотреть возможность миграции на архитектуру на основе шлюзов, как только количество агентов превысит несколько сотен. Эта архитектура имеет несколько недостатков, которые делают ее сложной для масштабирования:
- Масштабируемость соединений - Каждый агент устанавливает соединение с ClickHouse. Хотя ClickHouse способен поддерживать сотни (если не тысячи) параллельных соединений для вставок, в конечном итоге это станет ограничивающим фактором и сделает вставки менее эффективными - т.е. больше ресурсов будет использовано ClickHouse для поддержания соединений. Использование шлюзов минимизирует количество соединений и делает вставки более эффективными.
- Обработка на краю - Любые преобразования или обработка событий должны осуществляться на краю или в ClickHouse в этой архитектуре. Кроме того, что это ограничительно, это может означать сложные материализованные представления ClickHouse или перенос значительных вычислений на край - где критически важные сервисы могут пострадать, а ресурсы будут дефицитом.
- Малые пакеты и задержки - Коллекторы-агенты могут отдельно собирать очень мало событий. Это, как правило, означает, что они должны быть настроены на сброс через заданный интервал, чтобы удовлетворить SLA доставки. Это может привести к тому, что коллектор отправляет небольшие пакеты в ClickHouse. Хотя это и является недостатком, это можно смягчить с помощью асинхронных вставок - см. Оптимизация вставок.
Масштабирование с помощью шлюзов
Коллекторы OTel могут быть развернуты в виде экземпляров шлюза для устранения вышеуказанных ограничений. Эти экземпляры предоставляют автономный сервис, как правило, по центру обработки данных или региону. Эти экземпляры получают события от приложений (или других сборщиков в роли агента) через одну конечную точку OTLP. Обычно развертывается набор экземпляров шлюзов, к которым используется встроенный балансировщик нагрузки для распределения нагрузки между ними.

Цель этой архитектуры - разгрузить вычислительно интенсивную обработку от агентов, тем самым минимизируя их использование ресурсов. Эти шлюзы могут выполнять задачи преобразования, которые иначе пришлось бы выполнять агентам. Более того, агрегируя события от множества агентов, шлюзы могут гарантировать, что большие пакеты отправляются в ClickHouse, что позволяет выполнять эффективные вставки. Эти сборщики шлюзов можно легко масштабировать по мере добавления новых агентов и увеличения пропускной способности событий. Пример конфигурации шлюза с соответствующей конфигурацией агента, обрабатывающего пример структурированного лог-файла, показан ниже. Обратите внимание на использование OTLP для связи между агентом и шлюзом.
clickhouse-gateway-config.yaml
Эти конфигурации могут быть запущены с помощью следующих команд.
Основной недостаток этой архитектуры заключается в связанных затратах и накладных расходах на управление набором коллектора.
Для примера управления более крупными архитектурами на основе шлюзов с соответствующим обучением мы рекомендуем этот блог.
Добавление Kafka
Читатели могут заметить, что вышеуказанные архитектуры не используют Kafka как очередь сообщений.
Использование очереди Kafka в качестве буфера сообщений является популярным шаблоном проектирования в архитектурах журналирования и было популяризировано стеком ELK. Это предоставляет несколько преимуществ; в первую очередь, это помогает обеспечить более строгие гарантии доставки сообщений и помогает справиться с обратным давлением. Сообщения отправляются от агентов сбора данных в Kafka и записываются на диск. В теории кластерированная экземпляр Kafka должен обеспечивать высокопропускной буфер сообщений, так как в нем возникает меньше вычислительных накладных расходов на линейную запись данных на диск, чем на парсинг и обработку сообщения - в Elastic, например, токенизация и индексирование вызывают значительные накладные расходы. Перемещая данные от агентов, вы также подвергаетесь меньшему риску потери сообщений в результате ротации журналов на источнике. Наконец, это предоставляет некоторые возможности для ответа сообщений и межрегиональной репликации, что может быть привлекательно для некоторых случаев использования.
Тем не менее, ClickHouse может обрабатывать вставку данных очень быстро - миллионы строк в секунду на умеренном оборудовании. Обратное давление от ClickHouse - это редкость. Часто использование очереди Kafka означает больше архитектурной сложности и затрат. Если вы можете принять принцип, что логи не требуют тех же гарантий доставки, что и банковские транзакции и другие критически важные данные, мы рекомендуем избегать сложности Kafka.
Однако, если вам требуются высокие гарантии доставки или возможность воспроизводить данные (возможно, на несколько источников), Kafka может быть полезным архитектурным дополнением.

В этом случае агенты OTel могут быть настроены на отправку данных в Kafka через экспортер Kafka. Экземпляры шлюза, в свою очередь, обрабатывают сообщения с помощью приемника Kafka. Мы рекомендуем документацию Confluent и OTel для получения дальнейших деталей.
Оценка ресурсов
Требования к ресурсам для коллектора OTel будут зависеть от пропускной способности событий, размера сообщений и объема проводимой обработки. Проект OpenTelemetry поддерживает бенчмарки, которые пользователи могут использовать для оценки требований к ресурсам.
По нашему опыту, экземпляр шлюза с 3 ядрами и 12 ГБ ОЗУ может обрабатывать около 60 000 событий в секунду. Это предполагает минимальную обработку, отвечающую за переименование полей и без регулярных выражений.
Для экземпляров агентов, отвечающих за отправку событий в шлюз и устанавливающих только метку времени события, мы рекомендуем пользователям рассчитывать размеры на основе предполагаемых логов в секунду. Следующие представляют собой приблизительные цифры, которые пользователи могут использовать в качестве отправной точки:
Скорость логирования | Ресурсы для коллектора-агента |
---|---|
1k/секунда | 0.2 CPU, 0.2 GiB |
5k/секунда | 0.5 CPU, 0.5 GiB |
10k/секунда | 1 CPU, 1 GiB |