ClickHouse JS
官方 JS 客户端用于连接 ClickHouse。该客户端使用 TypeScript 编写,并提供客户端公共 API 的类型定义。
该客户端没有依赖,经过优化以实现最大性能,并与多种 ClickHouse 版本和配置进行了测试(本地单节点、本地集群和 ClickHouse Cloud)。
客户端有两个不同版本,适用于不同环境:
@clickhouse/client
- 仅适用于 Node.js@clickhouse/client-web
- 浏览器(Chrome/Firefox)、Cloudflare workers
使用 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 workers 的依赖。
安装
要安装最新稳定的 Node.js 客户端版本,请运行:
网页版本的安装:
与 ClickHouse 的兼容性
客户端版本 | ClickHouse |
---|---|
1.8.0 | 23.3+ |
可能客户端也能与较旧的版本工作;然而,这只是最佳努力支持,不提供保证。如果您的 ClickHouse 版本低于 23.3,请参考 ClickHouse 安全政策 并考虑升级。
示例
我们旨在通过客户端仓库中的 示例 覆盖客户端使用的各种场景。
概述可在 示例 README 中找到。
如果在示例或以下文档中有任何不清楚或缺失的内容,请随时 联系我们。
客户端 API
除非另有明确说明,绝大多数示例应与 Node.js 和 Web 版本的客户端兼容。
创建客户端实例
您可以使用 createClient
工厂创建任意数量的客户端实例:
如果您的环境不支持 ESM 模块,您可以改用 CJS 语法:
客户端实例可以在实例化时 预配置。
配置
在创建客户端实例时,可以调整以下连接设置:
设置 | 描述 | 默认值 | 参见 |
---|---|---|---|
url?: string | ClickHouse 实例的 URL。 | http://localhost:8123 | URL 配置文档 |
pathname?: string | 要添加到解析后的 ClickHouse URL 的可选路径。 | '' | 带路径的代理文档 |
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 会话 ID,随每个请求发送。 | - | - |
keep_alive?: { **enabled**?: boolean } | 在 Node.js 和 Web 版本中默认启用。 | - | - |
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 } | - | - | 保持活动配置 |
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¶m2=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) |
(仅限 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
的布尔值应在 URL 中以 1
/0
传递。
- (3) 与 (2) 类似,但用于
http_header
配置。例如,?http_header_x-clickhouse-auth=foobar
将等同于:
连接
收集您的连接详情
要通过 HTTP(S) 连接到 ClickHouse,您需要以下信息:
-
HOST 和 PORT:通常,当使用 TLS 时,端口为 8443;当不使用 TLS 时,端口为 8123。
-
数据库名称:开箱即用时,有一个名为
default
的数据库,请使用您要连接的数据库名称。 -
用户名和密码:开箱即用时,用户名为
default
。请使用适合您用例的用户名。
您的 ClickHouse Cloud 服务详细信息可在 ClickHouse Cloud 控制台中找到。 选择您要连接的服务并点击 Connect:

选择 HTTPS,详细信息会在示例 curl
命令中提供。

如果您使用的是自管理的 ClickHouse,连接详细信息由您的 ClickHouse 管理员设置。
连接概述
客户端通过 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
,否则没有保证池中的相同连接将被用于后续查询。这很少需要,但在用户使用临时表的情况下可能需要。
另请参见:保持活动配置。
查询 ID
每个发送查询或语句(command
、exec
、insert
、select
)的方法将在结果中提供 query_id
。此唯一标识符由客户端为每个查询分配,若启用了 server configuration,则可能有助于从 system.query_log
中获取数据,或取消长时间运行的查询(请参见 示例)。如果需要,用户可以在 command
/query
/exec
/insert
方法参数中覆盖 query_id
。
如果您覆盖 query_id
参数,请确保每次调用其唯一性。随机 UUID 是一个不错的选择。
所有客户端方法的基础参数
有几个参数可以应用于所有客户端方法(query/command/insert/exec)。
查询方法
此方法用于大多数可以返回响应的语句,例如 SELECT
,或用于发送 DDL(例如 CREATE TABLE
),并且应等待对应结果。期望返回的结果集将在应用程序中消费。
另请参见:所有客户端方法的基础参数。
请勿在 query
中指定 FORMAT 子句,请使用 format
参数代替。
结果集和行抽象
ResultSet
提供了一些方便的方法以处理您应用程序中的数据。
Node.js 的 ResultSet
实现使用 Stream.Readable
,而网页版本使用 Web API 的 ReadableStream
。
您可以通过调用 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) 以 JSONEachRow
格式流式查询结果,使用 for await const
语法消费为 JS 对象。此方法可与经典的 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
promise)。这可能对事件监听器和类似的场景很有用,但错误处理可能会比较复杂,有许多边缘情况出现在客户端。相反,考虑使用 异步插入,如 这个示例 所示。
如果您有一个难以通过此方法建模的自定义 INSERT 语句,考虑使用 命令方法。
您可以在 INSERT INTO ... VALUES 或 INSERT INTO ... SELECT 示例中看到它是如何使用的。
另请参阅:所有客户端方法的基本参数。
用 abort_signal
取消的请求并不能保证数据未被插入,因为服务器在取消之前可能已经接收到了一些流数据。
示例: (Node.js/Web) 插入一个值数组。 源代码。
示例: (仅限 Node.js) 从 CSV 文件插入一个流。 源代码。另请参阅:文件流。
示例: 从插入语句中排除某些列。
假设有以下表定义:
仅插入特定列:
排除某些列:
有关更多细节,请查看 源代码。
示例: 插入到与提供给客户端实例不同的数据库中。 源代码。
Web 版本的限制
目前,@clickhouse/client-web
中的插入仅适用于 Array<T>
和 JSON*
格式。
由于浏览器兼容性较差,Web 版本尚不支持插入流。
因此,Web 版本的 InsertParams
接口与 Node.js 版本略有不同,
因为 values
限制为 ReadonlyArray<T>
类型:
未来可能会有所改动。另请参阅:所有客户端方法的基本参数。
命令方法
它可用于没有任何输出的语句,当格式子句不适用,或者当您根本不关注响应时。这样的语句的例子可以是 CREATE TABLE
或 ALTER TABLE
。
应被等待。
响应流会立即被销毁,这意味着底层的套接字被释放。
另请参阅:所有客户端方法的基本参数。
示例: (Node.js/Web) 在 ClickHouse Cloud 中创建一个表。 源代码。
示例: (Node.js/Web) 在自托管的 ClickHouse 实例中创建一个表。 源代码。
示例: (Node.js/Web) 从选择插入。
用 abort_signal
取消的请求并不能保证服务器没有执行该语句。
执行方法
如果您有一个不适合 query
/insert
的自定义查询,并且您对此结果感兴趣,则可以使用 exec
作为 command
的替代。
exec
返回一个可读流,必须在应用程序一侧消费或销毁。
另请参阅:所有客户端方法的基本参数。
流返回类型在 Node.js 和 Web 版本中不同。
Node.js:
Web:
Ping
提供的 ping
方法用于检查连接状态,如果服务器可以访问,则返回 true
。
如果服务器无法访问,则底层错误也包含在结果中。
Ping 可能是检查服务器在应用程序启动时是否可用的有用工具,特别是在 ClickHouse Cloud 中,实例可能处于空闲状态,会在 ping 后唤醒。
示例: (Node.js/Web) Ping 一个 ClickHouse 服务器实例。注意:对于 Web 版本,捕获的错误将不同。 源代码。
注意:由于 /ping
端点没有实现 CORS,Web 版本使用简单的 SELECT 1
来实现类似的结果。
关闭(仅限 Node.js)
关闭所有打开的连接并释放资源。在 Web 版本中无操作。
流文件(仅限 Node.js)
在客户端库中有几个文件流示例,使用流行的数据格式(NDJSON、CSV、Parquet)。
将其他格式流入文件应与 Parquet 类似,
唯一的区别将在于用于 query
调用的格式(JSONEachRow
、CSV
等)以及输出文件名。
支持的数据格式
客户端将数据格式处理为 JSON 或文本。
如果将 format
指定为 JSON 系列之一(JSONEachRow
、JSONCompactEachRow
等),则客户端将在通信过程中对数据进行序列化和反序列化。
以“原始”文本格式(CSV
、TabSeparated
和 CustomSeparated
系列)提供的数据将以原样发送,而不会进行额外的转换。
在 JSON 作为通用格式和 ClickHouse JSON 格式 之间可能会产生混淆。
客户端支持使用像 JSONEachRow 这样的格式流式处理 JSON 对象(请参阅表概述以获取其他流友好的格式;另请参阅客户端库中的 select_streaming_
示例)。
只不过像 ClickHouse JSON 和其他一些格式在响应中表示为一个单一对象,客户端无法流式处理。
格式 | 输入(数组) | 输入(对象) | 输入/输出(流) | 输出(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[] |
(new) JSON | ✔️ | object |
Variant(T1, T2...) | ✔️ | T (取决于变体) |
Dynamic | ✔️ | T (取决于变体) |
Nested | ✔️ | T[] |
Tuple | ✔️ | Tuple |
Nullable(T) | ✔️ | T或null 的 JS 类型 |
IPv4 | ✔️ | string |
IPv6 | ✔️ | string |
Point | ✔️ | [ number, number ] |
Ring | ✔️ | Array<Point> |
Polygon | ✔️ | Array<Ring> |
MultiPolygon | ✔️ | Array<Polygon> |
Map(K, V) | ✔️ | Record<K, V> |
ClickHouse 支持的格式的完整列表可在 这里 找到。
日期/Date32 类型的注意事项
由于客户端在插入值时没有额外的类型转换,Date
/Date32
类型的列只能作为字符串插入。
示例: 插入 Date
类型值。
源代码 。
然而,如果您使用的是 DateTime
或 DateTime64
列,您可以使用字符串和 JS Date 对象。可以直接将 JS Date 对象传递给 insert
,并将 date_time_input_format
设置为 best_effort
。有关更多细节,请参见 这个示例。
Decimal* 类型的注意事项
可以使用 JSON*
系列格式插入 Decimals。假设我们有一个表定义如下:
我们可以使用字符串表示法插入值而没有精度损失:
然而,在以 JSON*
格式查询数据时,ClickHouse 会默认将 Decimals 返回为 数字,这可能会导致精度损失。为避免此情况,您可以在查询中将 Decimals 转换为字符串:
有关更多细节,请参见 这个示例。
整数类型:Int64、Int128、Int256、UInt64、UInt128、UInt256
尽管服务器可以将其作为数字接受,但在 JSON*
系列输出格式中返回时,它会作为字符串返回,以避免整数溢出,因为这些类型的最大值大于 Number.MAX_SAFE_INTEGER
。
然而,这种行为可以通过 output_format_json_quote_64bit_integers
设置 进行修改。
示例: 调整 64 位数字的 JSON 输出格式。
ClickHouse 设置
客户端可以通过 设置 机制调整 ClickHouse 的行为。 可在客户端实例级别设置设置,以便在发送到 ClickHouse 的每个请求中应用:
或者可以在请求级别配置设置:
有关所有受支持的 ClickHouse 设置的类型声明文件可以在 这里 找到。
确保以该用户身份执行查询的用户拥有更改设置的足够权限。
高级主题
带参数的查询
您可以创建一个带参数的查询,并从客户端应用程序传递值给它。这可以避免在客户端格式化查询时包含具体的动态值。
像往常一样格式化查询,然后将要从应用程序参数传递给查询的值放在大括号中,格式如下:
其中:
name
— 占位符标识符。data_type
- 数据类型 的应用参数值。
示例: 使用参数的查询。 源代码。
有关更多详细信息,请访问 https://clickhouse.com/docs/interfaces/cli#cli-queries-with-parameters-syntax。
压缩
注意:请求压缩目前在 Web 版本中不可用。响应压缩正常工作。Node.js 版本支持两者。
处理大量数据集的数据应用程序可以通过启用压缩受益。当前,仅支持 GZIP
,使用 zlib。
配置参数为:
response: true
指示 ClickHouse 服务器以压缩的响应主体响应。默认值:response: false
request: true
在客户端请求主体上启用压缩。默认值:request: false
日志记录(仅限 Node.js)
日志记录是实验性功能,未来可能会更改。
默认的日志记录实现通过 console.debug/info/warn/error
方法将日志记录到 stdout
。
您可以通过提供 LoggerClass
来自定义日志记录逻辑,并通过 level
参数选择所需的日志级别(默认值为 OFF
):
目前,客户端将记录以下事件:
TRACE
- 有关保持活动套接字生命周期的低级信息DEBUG
- 响应信息(不包括授权头和主机信息)INFO
- 大多未使用,初始化客户端时将打印当前日志级别WARN
- 非致命错误;失败的ping
请求记录为警告,底层错误包括在返回的结果中ERROR
- 来自query
/insert
/exec
/command
方法的致命错误,例如请求失败
您可以在 这里 找到默认的 Logger 实现。
TLS 证书(仅限 Node.js)
Node.js 客户端可以选择支持基础(仅证书颁发机构)和互相(证书颁发机构和客户端证书)TLS。
基础 TLS 配置示例,假设您的证书在 certs
文件夹中,并且 CA 文件名为 CA.pem
:
使用客户端证书的互相 TLS 配置示例:
Keep-Alive 配置(仅限 Node.js)
客户端默认在底层 HTTP 代理中启用 Keep-Alive,这意味着连接的套接字将在后续请求中重用,并且将发送 Connection: keep-alive
头。闲置的套接字将在默认情况下保持在连接池中 2500 毫秒(请参阅 调整此选项的说明)。
keep_alive.idle_socket_ttl
应该设置为比服务器/LB 配置低很多的值。主要原因是由于 HTTP/1.1 允许服务器在不通知客户端的情况下关闭套接字,如果服务器或负载均衡器在客户端之前关闭连接,客户端可能会尝试重用关闭的套接字,从而导致 socket hang up
错误。
如果您要调整 keep_alive.idle_socket_ttl
,请记住,它应始终与服务器/LB 的 Keep-Alive 配置保持同步,并且应该始终低于该值,以确保服务器不会先关闭打开的连接。
调整 idle_socket_ttl
客户端将 keep_alive.idle_socket_ttl
设置为 2500 毫秒,因为可以视为最安全的默认设置;在服务器端,keep_alive_timeout
在 ClickHouse 版本 23.11 之前可能被设置为 低至 3 秒,而无需 config.xml
修改。
如果您对性能很满意且没有遇到任何问题,建议 不 增加 keep_alive.idle_socket_ttl
设置的值,因为这可能会导致潜在的“套接字挂起”错误;另外,如果您的应用程序发送大量查询而两者之间没有太多停机时间,则默认值应该足够,因为套接字在长时间闲置之前不会闲置,客户端将保持它们在池中。
您可以通过运行以下命令查找正确的 Keep-Alive 超时值:
检查响应中的 Connection
和 Keep-Alive
头的值。例如:
在此情况下,keep_alive_timeout
为 10 秒,您可以尝试将 keep_alive.idle_socket_ttl
增加到 9000 或甚至 9500 毫秒,以保持闲置套接字开放的时间比默认值长一些。密切关注潜在的“套接字挂起”错误,这将表示服务器在客户端之前关闭连接,并降低值,直到错误消失。
Keep-Alive 故障排除
如果您在使用 Keep-Alive 时遇到 socket hang up
错误,可以考虑以下选项来解决此问题:
-
在 ClickHouse 服务器配置中稍微减少
keep_alive.idle_socket_ttl
设置。在某些情况下,例如客户端与服务器之间的网络延迟较高,减少keep_alive.idle_socket_ttl
200-500 毫秒可能是有益的,以排除一个即将由服务器关闭的 socket 被外出的请求获取的情况。 -
如果这个错误发生在没有数据进出的长时间运行的查询中(例如,一次长时间运行的
INSERT FROM SELECT
),这可能是因为负载均衡器关闭了空闲连接。您可以尝试通过使用以下 ClickHouse 设置的组合,强制在长时间运行的查询中有一些数据进来:然而请记住,最近的 Node.js 版本中接收的头的总大小有 16KB 限制;在接收到的进度头达到一定数量后(在我们的测试中约为 70-80),将生成异常。
也可以采用一种完全不同的方法,完全避免在网络上等待时间;这可以通过利用 HTTP 接口的“功能”来实现,即在连接丢失时不会取消变更。有关更多详细信息,请参见 这个示例(第2部分)。
-
可以完全禁用 Keep-Alive 功能。在这种情况下,客户端也会在每个请求中添加
Connection: close
头,底层 HTTP 代理将不会重用连接。keep_alive.idle_socket_ttl
设置将被忽略,因为将没有空闲的 sockets。这将导致额外的开销,因为每个请求将建立新的连接。
只读用户
当使用带有 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)
这是一个实验性特性,未来的版本中可能会以不兼容的方式更改。客户端提供的默认实现和设置对于大多数用例来说应该是足够的。仅在您确定需要时使用此功能。
默认情况下,客户端将使用在客户端配置中提供的设置(例如 max_open_connections
、 keep_alive.enabled
、 tls
)配置底层 HTTP(s) 代理,该代理将处理与 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 socket 管理仍然有效(因为它不与代理相关,而是与特定 socket 本身相关),现在可以通过将
keep_alive.idle_socket_ttl
值设置为0
来完全禁用它。
自定义代理用例示例
使用不带证书的自定义 HTTP(s) 代理:
使用带基本 TLS 和 CA 证书的自定义 HTTPS 代理:
使用带有双向 TLS 的自定义 HTTPS 代理:
使用证书 和 自定义 HTTPS 代理,可能需要通过 set_basic_auth_header
设置(在 1.2.0 中引入)禁用默认的授权头,因为它与 TLS 头冲突。所有的 TLS 头应手动提供。
已知限制 (Node.js/Web)
- 结果集没有数据映射器,因此仅使用语言原始类型。计划添加某些数据类型映射器和 RowBinary 格式支持。
- 有一些 Decimal* 和 Date* / DateTime* 数据类型的注意事项。
- 使用 JSON* 家族格式时,超出 Int32 的数字以字符串形式呈现,因为 Int64+ 类型的最大值大于
Number.MAX_SAFE_INTEGER
。有关更多详细信息,请参见 Integral types 部分。
已知限制 (Web)
- 选择查询的流式传输有效,但在插入(在类型级别也禁用)时无效。
- 请求压缩已禁用,配置被忽略。响应压缩有效。
- 尚无日志支持。
性能优化建议
- 为了减少应用程序的内存消耗,考虑在适用时使用流进行大规模插入(例如,从文件)和选择。对于事件监听器和类似用例,异步插入 可能是另一个不错的选择,这样可以最小化,甚至完全避免客户端的批处理。异步插入示例可在 客户端库 中找到,文件名以
async_insert_
为前缀。 - 客户端默认不启用请求或响应压缩。但是,在选择或插入大型数据集时,您可以考虑通过
ClickHouseClientConfigOptions.compression
启用它(针对request
或response
,或两者)。 - 压缩会带来显著的性能损失。启用
request
或response
将对选择或插入的速度产生负面影响,但会减少应用程序传输的网络流量。
联系我们
如果您有任何问题或需要帮助,请随时在 社区 Slack (#clickhouse-js
频道) 或通过 GitHub 问题 联系我们。