Перейти к основному содержимому
Перейти к основному содержимому

ClickHouse JS

Официальный JS-клиент для подключения к ClickHouse. Клиент написан на TypeScript и предоставляет типы для публичного API клиента.

У него нет зависимостей, он оптимизирован для максимальной производительности и протестирован с различными версиями и конфигурациями ClickHouse (локальный одиночный узел, кластер на месте и ClickHouse Cloud).

Существует две разные версии клиента для различных сред:

  • @clickhouse/client - только Node.js
  • @clickhouse/client-web - браузеры (Chrome/Firefox), рабочие процессы Cloudflare

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

Исходный код клиента доступен в репозитории ClickHouse-JS на GitHub.

Требования к среде (Node.js)

Node.js должен быть доступен в среде для работы клиента. Клиент совместим со всеми поддерживаемыми версиями Node.js.

Как только версия Node.js становится устаревшей, клиент прекращает его поддержку, так как считается не безопасной.

Текущие поддерживаемые версии Node.js:

Версия Node.jsПоддерживаемая?
22.x
20.x
18.x
16.xМаксимально возможная

Требования к среде (Web)

Веб-версия клиента официально протестирована с последними браузерами Chrome/Firefox и может использоваться как зависимость, например, в приложениях на React/Vue/Angular или рабочих процессах Cloudflare.

Установка

Чтобы установить последнюю стабильную версию клиента для Node.js, выполните:

Установка веб-версии:

Совместимость с ClickHouse

Версия клиентаClickHouse
1.8.023.3+

Вероятно, клиент будет работать и с более старыми версиями; однако это поддержка осуществляется без гарантий. Если у вас версия ClickHouse ниже 23.3, пожалуйста, обратитесь к политике безопасности ClickHouse и подумайте об обновлении.

Примеры

Мы стремимся охватить различные сценарии использования клиента в примерах в репозитории клиента.

Обзор доступен в README примеров.

Если что-то непонятно или отсутствует в примерах или в следующей документации, не стесняйтесь связаться с нами.

API клиента

Большинство примеров должны быть совместимы как с версиями для Node.js, так и с веб-версиями клиента, если не указано иное.

Создание экземпляра клиента

Вы можете создавать столько экземпляров клиента, сколько необходимо, с помощью фабрики createClient:

Если ваша среда не поддерживает ESM модули, вы можете использовать синтаксис CJS:

Экземпляр клиента может быть предварительно настроен во время инстанцирования.

Конфигурация

При создании экземпляра клиента можно настроить следующие параметры подключения:

ПараметрОписаниеЗначение по умолчаниюСм. Также
url?: stringURL экземпляра ClickHouse.http://localhost:8123Документация по конфигурации URL
pathname?: stringНеобязательный путь, который можно добавить к URL ClickHouse после его разбора клиентом.''Прокси с путем документация
request_timeout?: numberВремя ожидания запроса в миллисекундах.30_000-
compression?: { **response**?: boolean; **request**?: boolean }Включить сжатие.-Документация по сжатию
username?: stringИмя пользователя, от имени которого выполняются запросы.default-
password?: stringПароль пользователя.''-
application?: stringИмя приложения, использующего клиент Node.js.clickhouse-js-
database?: stringИмя используемой базы данных.default-
clickhouse_settings?: ClickHouseSettingsНастройки ClickHouse, которые будут применены ко всем запросам.{}-
log?: { **LoggerClass**?: Logger, **level**?: ClickHouseLogLevel }Конфигурация внутренних логов клиента.-Документация по логированию
session_id?: stringНеобязательный идентификатор сессии ClickHouse, который отправляется с каждым запросом.--
keep_alive?: { **enabled**?: boolean }Включен по умолчанию как в Node.js, так и в веб-версиях.--
http_headers?: Record<string, string>Дополнительные HTTP заголовки для исходящих запросов ClickHouse.-Документация по обратному прокси с аутентификацией
roles?: string | string[]Имена ролей ClickHouse для прикрепления к исходящим запросам.-Использование ролей с HTTP интерфейсом

Параметры конфигурации, специфичные для Node.js

ПараметрОписаниеЗначение по умолчаниюСм. Также
max_open_connections?: numberМаксимальное количество подключенных сокетов, разрешенное на один хост.10-
tls?: { **ca_cert**: Buffer, **cert**?: Buffer, **key**?: Buffer }Настройка сертификатов TLS.-Документация по TLS
keep_alive?: { **enabled**?: boolean, **idle_socket_ttl**?: number }--Документация по Keep Alive
http_agent?: http.Agent | https.Agent
Experimental feature. Learn more.
Пользовательский HTTP-агент для клиента.-Документация по HTTP-агенту
set_basic_auth_header?: boolean
Experimental feature. Learn more.
Установить заголовок Authorization с учетными данными базовой аутентификации.trueиспользование этого параметра в документации HTTP-агента

Конфигурация URL

к сведению

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

Возможно настроить большинство параметров экземпляра клиента с помощью URL. Формат URL: http[s]://[username:password@]hostname:port[/database][?param1=value1&param2=value2]. В большинстве случаев название конкретного параметра отражает его путь в интерфейсе параметров конфигурации, с несколькими исключениями. Поддерживаются следующие параметры:

ПараметрТип
pathnameпроизвольная строка.
application_idпроизвольная строка.
session_idпроизвольная строка.
request_timeoutнеотрицательное число.
max_open_connectionsнеотрицательное число, больше нуля.
compression_requestлогический. См. ниже (1)
compression_responseлогический.
log_levelдопустимые значения: OFF, TRACE, DEBUG, INFO, WARN, ERROR.
keep_alive_enabledлогический.
clickhouse_setting_* или ch_*см. ниже (2)
http_header_*см. ниже (3)
(только для Node.js) keep_alive_idle_socket_ttlнеотрицательное число.
  • (1) Для логических значений допустимыми значениями будут true/1 и false/0.
  • (2) Любой параметр, начинающийся с clickhouse_setting_ или ch_, будет иметь этот префикс удаленным, а остальная часть будет добавлена к clickhouse_settings клиента. Например, ?ch_async_insert=1&ch_wait_for_async_insert=1 будет таким же, как:

Примечание: логические значения для clickhouse_settings должны передаваться как 1/0 в URL.

  • (3) Похоже на (2), но для конфигурации http_header. Например, ?http_header_x-clickhouse-auth=foobar будет эквивалентно:

Подключение

Соберите свои данные подключения

To connect to ClickHouse with HTTP(S) you need this information:

  • The HOST and PORT: typically, the port is 8443 when using TLS or 8123 when not using TLS.

  • The DATABASE NAME: out of the box, there is a database named default, use the name of the database that you want to connect to.

  • The USERNAME and PASSWORD: out of the box, the username is default. Use the username appropriate for your use case.

The details for your ClickHouse Cloud service are available in the ClickHouse Cloud console. Select the service that you will connect to and click Connect:

Choose HTTPS, and the details are available in an example curl command.

If you are using self-managed ClickHouse, the connection details are set by your ClickHouse administrator.

Обзор подключения

Клиент реализует подключение через протокол HTTP(s). Поддержка RowBinary в процессе разработки, см. соответствующий вопрос.

Следующий пример демонстрирует, как настроить подключение к ClickHouse Cloud. Предполагается, что url (включая протокол и порт) и password указаны через переменные окружения, а используется пользователь default.

Пример: Создание экземпляра клиента Node.js с использованием переменных окружения для конфигурации.

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

Пул подключений (только для Node.js)

Чтобы избежать накладных расходов на установление соединения при каждом запросе, клиент создает пул подключений к ClickHouse для повторного использования, используя механизм Keep-Alive. По умолчанию Keep-Alive включен, а размер пула подключений установлен на 10, но вы можете изменить его с помощью параметра max_open_connections опции конфигурации.

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

См. также: Конфигурация Keep-Alive.

Идентификатор запроса

Каждый метод, который отправляет запрос или оператор (command, exec, insert, select), предоставит query_id в результате. Этот уникальный идентификатор назначается клиентом на каждый запрос и может быть полезен для получения данных из system.query_log, если он включен в конфигурации сервера, или для отмены долгих запросов (см. пример). При необходимости query_id может быть переопределен пользователем в параметрах методов command/query/exec/insert.

подсказка

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

Базовые параметры для всех методов клиента

Существует несколько параметров, которые могут быть применены ко всем методам клиента (query/command/insert/exec).

Метод запроса

Этот метод используется для большинства операторов, которые могут иметь ответ, таких как SELECT, или для отправки DDL, таких как CREATE TABLE, и должен ожидаться. Ожидается, что возвращаемый набор результатов будет потреблен в приложении.

примечание

Существует специальный метод insert для вставки данных и command для DDL.

См. также: Базовые параметры для всех методов клиента.

подсказка

Не указывайте оператор FORMAT в query, используйте вместо этого параметр format.

Набор результатов и абстракции строк

ResultSet предоставляет несколько удобных методов для обработки данных в вашем приложении.

Реализация ResultSet в Node.js использует Stream.Readable под капотом, в то время как веб-версия использует Web API ReadableStream.

Вы можете потреблять ResultSet, вызывая либо методы text, либо json на ResultSet, и загрузить весь набор строк, возвращенных запросом, в память.

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

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

Пожалуйста, обратитесь к списку поддерживаемых форматов данных, чтобы определить, какой формат лучше всего подходит для потоковой передачи в вашем случае. Например, если вы хотите потоково передавать JSON-объекты, вы можете выбрать JSONEachRow, и каждая строка будет разобрана как JS-объект, или, возможно, более компактный формат JSONCompactColumns, который приведет к тому, что каждая строка будет компактным массивом значений. См. также: поточные файлы.

к сведению

Если ResultSet или его поток не полностью потреблены, он будет уничтожен после истечения периода бездействия, равного request_timeout.

Пример: (Node.js/Web) Запрос с результатом в формате JSONEachRow, который потребляет весь поток и разбирает содержимое как JS-объекты. Исходный код.

Пример: (только Node.js) Потоковая передача результата запроса в формате JSONEachRow, используя классический подход on('data'). Это взаимозаменяемо с синтаксисом for await const. Исходный код.

Пример: (только Node.js) Потоковая передача результата запроса в формате CSV, используя классический подход on('data'). Это взаимозаменяемо с синтаксисом for await const. Исходный код

Пример: (только Node.js) Потоковая передача результата запроса как JS объектов в формате JSONEachRow, потребляемом с использованием синтаксиса for await const. Это взаимозаменяемо с классическим подходом on('data'). Исходный код.

примечание

Синтаксис for await const требует немного меньше кода, чем подход on('data'), но может иметь негативное влияние на производительность. Смотрите этот вопрос в репозитории Node.js для получения дополнительных деталей.

Пример: (только Web) Итерация по ReadableStream объектов.

Метод вставки

Это основной метод для вставки данных.

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

Если пустой массив был передан в метод вставки, оператор вставки не будет отправлен на сервер; вместо этого метод немедленно разрешится с { query_id: '...', executed: false }. Если параметр query_id не был предоставлен в параметрах метода, он будет пустой строкой в результате, так как возврат случайного UUID, сгенерированного клиентом, может вызвать путаницу, так как запрос с таким query_id не будет существовать в таблице system.query_log.

Если оператор вставки был отправлен на сервер, флаг executed будет true.

Метод вставки и потоковая передача в Node.js

Он может работать как с Stream.Readable, так и с обычным Array<T>, в зависимости от формата данных, указанных в методе insert. См. также этот раздел о потоковой передаче файлов.

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

подсказка

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

Вы можете увидеть, как он используется в примерах INSERT INTO ... VALUES или INSERT INTO ... SELECT.

См. также: Базовые параметры для всех клиентских методов.

к сведению

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

Пример: (Node.js/Web) Вставка массива значений. Исходный код.

Пример: (Только Node.js) Вставка потока из CSV-файла. Исходный код. См. также: потоковая передача файлов.

Пример: Исключение определенных колонок из выражения вставки.

Учитывая следующее определение таблицы:

Вставьте только конкретную колонку:

Исключите определенные колонки:

Смотрите исходный код для получения дополнительной информации.

Пример: Вставка в базу данных, отличную от той, что была предоставлена экземпляру клиента. Исходный код.

Ограничения веб-версии

В настоящее время вставки в @clickhouse/client-web работают только с Array<T> и форматами JSON*. Вставка потоков в веб-версии пока не поддерживается из-за плохой совместимости браузеров.

Следовательно, интерфейс InsertParams для веб-версии выглядит немного иначе, чем версия для Node.js, так как values ограничены только типом ReadonlyArray<T>:

Это может измениться в будущем. См. также: Базовые параметры для всех клиентских методов.

Метод command

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

Должен ожидаться.

Поток ответа немедленно закрывается, что означает, что основной сокет освобождается.

См. также: Базовые параметры для всех клиентских методов.

Пример: (Node.js/Web) Создание таблицы в ClickHouse Cloud. Исходный код.

Пример: (Node.js/Web) Создание таблицы в самоуправляемом экземпляре ClickHouse. Исходный код.

Пример: (Node.js/Web) INSERT FROM SELECT

к сведению

Запрос, отмененный с помощью abort_signal, не гарантирует, что выражение не было выполнено сервером.

Метод exec

Если у вас есть пользовательский запрос, который не соответствует query/insert, и вас интересует результат, вы можете использовать exec как альтернативу command.

exec возвращает читаемый поток, который ДОЛЖЕН быть использован или уничтожен на стороне приложения.

См. также: Базовые параметры для всех клиентских методов.

Тип возвращаемого потока отличается в версиях Node.js и Web.

Node.js:

Web:

Ping

Метод ping, предоставляемый для проверки статуса соединения, возвращает true, если сервер доступен.

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

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

Пример: (Node.js/Web) Пинг экземпляра сервера ClickHouse. Обратите внимание: для веб-версии захваченные ошибки будут другими. Исходный код.

Обратите внимание: из-за того, что конечная точка /ping не реализует CORS, веб-версия использует простой SELECT 1, чтобы достичь аналогичного результата.

Закрытие (только Node.js)

Закрывает все открытые соединения и освобождает ресурсы. Не выполняется в веб-версии.

Потоковые файлы (только Node.js)

Существует несколько примеров потоковой передачи файлов с популярными форматами данных (NDJSON, CSV, Parquet) в репозитории клиента.

Потоковая передача других форматов в файл должна быть похожа на Parquet, единственное отличие будет в формате, используемом для вызова query (JSONEachRow, CSV и т. д.) и имени выходного файла.

Поддерживаемые форматы данных

Клиент обрабатывает форматы данных как JSON или текст.

Если вы укажете format как один из форматов JSON-семейства (JSONEachRow, JSONCompactEachRow и т. д.), клиент будет сериализовать и десериализовать данные в процессе общения по проводу.

Данные, предоставленные в "сырых" текстовых форматах (CSV, TabSeparated и CustomSeparated), отправляются по проводу без дополнительных преобразований.

подсказка

Может возникнуть путаница между JSON как общим форматом и форматом JSON ClickHouse.

Клиент поддерживает потоковые JSON-объекты с такими форматами, как JSONEachRow (см. обзор таблицы для других форматов, удобных для потоковой передачи; смотрите также примеры select_streaming_ в репозитории клиента).

Лишь форматы, такие как JSON ClickHouse и несколько других, представлены в виде единого объекта в ответе и не могут быть переданы по потокам клиентом.

ФорматВход (массив)Вход (объект)Вход/выход (Поток)Выход (JSON)Выход (текст)
JSON✔️✔️✔️
JSONCompact✔️✔️✔️
JSONObjectEachRow✔️✔️✔️
JSONColumnsWithMetadata✔️✔️✔️
JSONStrings✔️✔️
JSONCompactStrings✔️✔️
JSONEachRow✔️✔️✔️✔️
JSONEachRowWithProgress✔️ ❗- см. ниже✔️✔️
JSONStringsEachRow✔️✔️✔️✔️
JSONCompactEachRow✔️✔️✔️✔️
JSONCompactStringsEachRow✔️✔️✔️✔️
JSONCompactEachRowWithNames✔️✔️✔️✔️
JSONCompactEachRowWithNamesAndTypes✔️✔️✔️✔️
JSONCompactStringsEachRowWithNames✔️✔️✔️✔️
JSONCompactStringsEachRowWithNamesAndTypes✔️✔️✔️✔️
CSV✔️✔️
CSVWithNames✔️✔️
CSVWithNamesAndTypes✔️✔️
TabSeparated✔️✔️
TabSeparatedRaw✔️✔️
TabSeparatedWithNames✔️✔️
TabSeparatedWithNamesAndTypes✔️✔️
CustomSeparated✔️✔️
CustomSeparatedWithNames✔️✔️
CustomSeparatedWithNamesAndTypes✔️✔️
Parquet✔️✔️❗- см. ниже

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

JSONEachRowWithProgress — это формат только для вывода, который поддерживает отчет о прогрессе в потоке. См. этот пример для получения дополнительной информации.

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

Поддерживаемые типы данных ClickHouse

примечание

Связанный тип JS актуален для любых форматов JSON*, кроме тех, которые представляют все в виде строки (например, JSONStringEachRow)

ТипСтатусТип JS
UInt8/16/32✔️number
UInt64/128/256✔️ ❗- см. нижеstring
Int8/16/32✔️number
Int64/128/256✔️ ❗- см. нижеstring
Float32/64✔️number
Decimal✔️ ❗- см. нижеnumber
Boolean✔️boolean
String✔️string
FixedString✔️string
UUID✔️string
Date32/64✔️string
DateTime32/64✔️ ❗- см. нижеstring
Enum✔️string
LowCardinality✔️string
Array(T)✔️T[]
(новый) JSON✔️object
Variant(T1, T2...)✔️T (в зависимости от варианта)
Dynamic✔️T (в зависимости от варианта)
Nested✔️T[]
Tuple✔️Tuple
Nullable(T)✔️JS тип для T или null
IPv4✔️string
IPv6✔️string
Point✔️[ number, number ]
Ring✔️Array<Point>
Polygon✔️Array<Ring>
MultiPolygon✔️Array<Polygon>
Map(K, V)✔️Record<K, V>

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

Ограничения типов Date/Date32

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

Пример: Вставка значения типа Date. Исходный код .

Однако, если вы используете столбцы DateTime или DateTime64, вы можете использовать как строки, так и объекты Date JS. Объекты Date JS могут быть переданы в insert как есть с установленным date_time_input_format в best_effort. Смотрите этот пример для получения дополнительной информации.

Ограничения типов Decimal*

Возможно вставка Decimals с использованием форматов семейства JSON*. Предположим, у нас есть определенная таблица:

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

Однако, при запросе данных в форматах JSON*, ClickHouse будет возвращать Decimals как числа по умолчанию, что может привести к потере точности. Чтобы избежать этого, вы можете преобразовать Decimals в строку в запросе:

Смотрите этот пример для получения дополнительной информации.

Целочисленные типы: Int64, Int128, Int256, UInt64, UInt128, UInt256

Хотя сервер может принимать это как число, в форматах вывода семейства JSON* это возвращается как строка, чтобы избежать переполнения целого числа, так как максимальные значения для этих типов больше, чем Number.MAX_SAFE_INTEGER.

Однако это поведение можно изменить с помощью output_format_json_quote_64bit_integers setting .

Пример: Настройка формата JSON для вывода 64-битных чисел.

Настройки ClickHouse

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

Или настройка может быть сконфигурирована на уровне запроса:

Файл декларации типов с поддерживаемыми настройками ClickHouse можно найти здесь.

к сведению

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

Расширенные темы

Запросы с параметрами

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

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

где:

  • name — идентификатор-заполнитель.
  • data_type - Тип данных значения параметра приложения.

Пример:: Запрос с параметрами. Исходный код .

Смотрите https://clickhouse.com/docs/interfaces/cli#cli-queries-with-parameters-syntax для получения дополнительных деталей.

Сжатие

Обратите внимание: сжатие запросов в настоящее время недоступно в веб-версии. Сжатие ответов работает нормально. В версии Node.js поддерживаются оба.

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

Параметры конфигурации:

  • response: true указывает серверу ClickHouse отвечать с сжатыми телами ответов. Значение по умолчанию: response: false
  • request: true включает сжатие на теле запроса клиента. Значение по умолчанию: request: false

Логирование (только Node.js)

к сведению

Логирование является экспериментальной функцией и может измениться в будущем.

Реализация по умолчанию регистрирует записи лога в stdout через методы console.debug/info/warn/error. Вы можете настроить логику логирования, предоставив LoggerClass, и выбрать желаемый уровень логирования через параметр level (по умолчанию OFF):

В настоящее время клиент будет регистрировать следующие события:

  • TRACE - информация низкого уровня о жизненном цикле сокетов Keep-Alive
  • DEBUG - информация о ответе (без заголовков авторизации и информации о хосте)
  • INFO - в основном неиспользуемая, будет печатать текущий уровень логирования при инициализации клиента
  • WARN - нефатальные ошибки; неудачный запрос ping регистрируется как предупреждение, так как основная ошибка включена в возвращаемый результат
  • ERROR - фатальные ошибки из методов query/insert/exec/command, такие как неудачный запрос

Вы можете найти реализацию стандартного логгера здесь.

TLS-сертификаты (только Node.js)

Клиент Node.js опционально поддерживает как базовое (только удостоверяющий центр) так и взаимное (удостоверяющий центр и клиентские сертификаты) TLS.

Пример конфигурации базового TLS, предполагая, что у вас есть свои сертификаты в папке certs и имя файла CA - CA.pem:

Пример конфигурации взаимного TLS с использованием клиентских сертификатов:

Смотрите полные примеры основного и взаимного TLS в репозитории.

Конфигурация Keep-Alive (только Node.js)

Клиент по умолчанию включает Keep-Alive в основном HTTP-агенте, что означает, что подключенные сокеты будут использоваться повторно для последующих запросов, а заголовок Connection: keep-alive будет отправлен. Соки, которые находятся в ожидании, будут оставаться в пуле соединений в течение 2500 миллисекунд по умолчанию (см. замечания о настройке этой опции).

keep_alive.idle_socket_ttl должен иметь значение значительно ниже, чем конфигурация сервера/LB. Основная причина в том, что из-за HTTP/1.1 сервер может закрывать сокеты без уведомления клиента: если сервер или балансировщик нагрузки закрывает соединение до того, как клиент, клиент может попытаться повторно использовать закрытый сокет, что приведет к ошибке socket hang up.

Если вы изменяете keep_alive.idle_socket_ttl, имейте в виду, что он всегда должен синхронизироваться с конфигурацией Keep-Alive вашего сервера/LB и он должен быть всегда ниже этой, чтобы гарантировать, что сервер никогда не закрывает открытое соединение первым.

Настройка idle_socket_ttl

Клиент устанавливает keep_alive.idle_socket_ttl в 2500 миллисекунд, так как это можно считать безопасным значением по умолчанию; на стороне сервера keep_alive_timeout может быть установлен даже на уровне 3 секунд в версиях ClickHouse до 23.11 без модификаций config.xml.

осторожно

Если вы довольны производительностью и не сталкиваетесь с какими-либо проблемами, рекомендуется не увеличивать значение параметра keep_alive.idle_socket_ttl, так как это может привести к потенциальным ошибкам "Socket hang-up"; кроме того, если ваше приложение отправляет много запросов и между ними не так много времени простоя, то значение по умолчанию должно быть достаточным, так как сокеты не будут находиться в ожидании достаточно долго, и клиент будет держать их в пуле.

Вы можете найти правильное значение таймаута Keep-Alive на сервере в заголовках ответа, выполнив следующую команду:

Проверьте значения заголовков Connection и Keep-Alive в ответе. Например:

В этом случае keep_alive_timeout составляет 10 секунд, и вы можете попробовать увеличить keep_alive.idle_socket_ttl до 9000 или даже 9500 миллисекунд, чтобы поддерживать открытыми ожидающие сокеты немного дольше, чем по умолчанию. Учтите потенциальные ошибки "Socket hang-up", которые укажут на то, что сервер закрывает соединения до того, как клиент, и уменьшите значение, пока ошибки не исчезнут.

Устранение неполадок Keep-Alive

Если вы сталкиваетесь с ошибками socket hang up при использовании Keep-Alive, существуют следующие варианты решения этой проблемы:

  • Ненадолго уменьшите настройку keep_alive.idle_socket_ttl в конфигурации сервера ClickHouse. В некоторых ситуациях, например, при высокой задержке сети между клиентом и сервером, может быть полезно уменьшить keep_alive.idle_socket_ttl еще на 200-500 миллисекунд, исключив ситуацию, когда исходящий запрос может получить сокет, который сервер собирается закрыть.

  • Если эта ошибка возникает во время длительных запросов, когда нет данных ни входящих, ни исходящих (например, долгий INSERT FROM SELECT), это может быть связано с тем, что балансировщик нагрузки закрывает неактивные соединения. Вы можете попробовать заставить некоторые данные входить во время длительных запросов, используя комбинацию следующих настроек ClickHouse:

    Тем не менее, имейте в виду, что общий размер полученных заголовков имеет лимит 16KB в последних версиях Node.js; после определенного количества полученных заголовков прогресса, которое в наших тестах составило около 70-80, будет сгенерировано исключение.

    Также возможно использовать совершенно другой подход, полностью избегая ожидания времени на линии; это можно сделать, воспользовавшись "функцией" HTTP интерфейса, что мутации не отменяются при потере соединения. См. этот пример (часть 2) для получения дополнительных сведений.

  • Функцию Keep-Alive можно отключить полностью. В этом случае клиент также добавит заголовок Connection: close к каждому запросу, и базовая HTTP-агент не будет повторно использовать соединения. Настройка keep_alive.idle_socket_ttl будет игнорироваться, так как не будет неактивных сокетов. Это приведет к дополнительным накладным расходам, так как для каждого запроса будет устанавливаться новое соединение.

Пользователи только для чтения

При использовании клиента с readonly=1 пользователем сжатие ответов не может быть включено, так как требуется настройка enable_http_compression. Следующая конфигурация приведет к ошибке:

См. пример, который содержит дополнительные акценты на ограничения пользователя readonly=1.

Прокси с путем

Если ваш экземпляр ClickHouse находится за прокси и в URL есть путь, как, например, http://proxy:8123/clickhouse_server, укажите clickhouse_server в качестве конфигурационной опции pathname (с ведущим слешем или без); в противном случае, если он будет указан напрямую в url, он будет рассматриваться как опция database. Поддерживаются несколько сегментов, например, /my_proxy/db.

Реверс-прокси с аутентификацией

Если у вас есть реверс-прокси с аутентификацией перед вашей разверткой ClickHouse, вы можете использовать настройку http_headers, чтобы предоставить необходимые заголовки:

Пользовательский HTTP/HTTPS-агент (экспериментально, только Node.js)

осторожно

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

По умолчанию клиент настраивает базовый HTTP(s) агент с использованием настроек, предоставленных в конфигурации клиента (таких как max_open_connections, keep_alive.enabled, tls), который будет обрабатывать соединения к серверу ClickHouse. Кроме того, если используются сертификаты TLS, базовый агент будет настроен с необходимыми сертификатами, и правильные заголовки аутентификации TLS будут применены.

После версии 1.2.0 вы можете предоставить пользовательский HTTP(s) агент клиенту, заменив стандартный. Это может быть полезно в случае сложных сетевых конфигураций. Применяются следующие условия, если предоставлен пользовательский агент:

  • Опции max_open_connections и tls не будут иметь никакого эффекта и будут игнорироваться клиентом, так как это часть конфигурации базового агента.
  • keep_alive.enabled будет регулировать только значение по умолчанию заголовка Connection (true -> Connection: keep-alive, false -> Connection: close).
  • Хотя управление неактивными сокетами в режиме keep-alive все еще будет работать (так как оно не связано с агентом, а с конкретным сокетом), теперь его можно отключить полностью, установив значение keep_alive.idle_socket_ttl в 0.

Примеры использования пользовательского агента

Использование пользовательского HTTP(s) агента без сертификатов:

Использование пользовательского HTTPS-агента с базовым TLS и сертификатом CA:

Использование пользовательского HTTPS-агента с взаимной TLS:

С сертификатами и пользовательским HTTPS агентом, вероятно, необходимо отключить стандартный заголовок авторизации через настройку set_basic_auth_header (введена в 1.2.0), так как он конфликтует с заголовками TLS. Все заголовки TLS должны быть предоставлены вручную.

Известные ограничения (Node.js/Web)

  • Нет преобразователей данных для наборов результатов, поэтому используются только примитивы языка. Определенные преобразователи типов данных планируются с поддержкой формата RowBinary.
  • Существуют некоторые ограничения типов данных Decimal* и Date* / DateTime*.
  • При использовании форматов семейства JSON* числа больше Int32 представлены в виде строк, так как максимальные значения типов Int64+ превышают Number.MAX_SAFE_INTEGER. См. раздел Целочисленные типы для получения дополнительных сведений.

Известные ограничения (Web)

  • Пакетная обработка для выборочных запросов работает, но отключена для вставок (так же на уровне типов).
  • Сжатие запросов отключено, и конфигурация игнорируется. Сжатие ответов работает.
  • Поддержка логирования еще не реализована.

Советы по оптимизации производительности

  • Для уменьшения потребления памяти приложением рассмотрите возможность использования потоков для больших вставок (например, из файлов) и выборок, когда это возможно. Для обработчиков событий и подобных случаев асинхронные вставки могут быть еще одним хорошим вариантом, позволяя минимизировать или даже полностью избежать пакетирования на стороне клиента. Примеры асинхронной вставки доступны в репозитории клиента, с префиксом имени файла async_insert_.
  • Клиент по умолчанию не включает сжатие запросов или ответов. Однако при выборке или вставке больших наборов данных вы можете рассмотреть возможность его включения через ClickHouseClientConfigOptions.compression (либо только для request, либо для response, либо для обоих).
  • Сжатие имеет значительные штрафы по производительности. Включение его для request или response отрицательно скажется на скорости выборок или вставок, соответственно, но уменьшит объем сетевого трафика, передаваемого приложением.

Свяжитесь с нами

Если у вас есть вопросы или нужна помощь, не стесняйтесь обращаться к нам в Community Slack (канал #clickhouse-js) или через GitHub issues.