十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

APISIX clickhouse-logger 插件实战:将网关访问日志批量写入 ClickHouse

APISIX clickhouse-logger 插件实战:将网关访问日志批量写入 ClickHouse APISIX clickhouse-logger 插件实战将网关访问日志批量写入 ClickHouse【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix导读clickhouse-logger是 Apache APISIX 内置的日志类插件插件名clickhouse-logger用于在请求生命周期结束时将 APISIX 产生的访问日志推送到 ClickHouse 数据库中适合需要将网关日志汇聚到 ClickHouse 做分析、告警与排障的场景。读完本文你将掌握该插件全部配置项的含义与默认值、基于批处理器的批量写入机制、自定义日志格式的方法以及从搭建 ClickHouse、建表、启用插件到验证落库的完整实操流程。插件作用与适用场景clickhouse-logger的核心能力是把 APISIX 在每个请求结束后生成的 JSON 日志条目写入 ClickHouse 表。它基于 HTTP 接口与 ClickHouse 通信通过INSERT INTO logtable FORMAT JSONEachRow的方式写入因此不需要在 APISIX 侧引入 ClickHouse 的专用客户端部署轻量。在 插件源码 中可以看到该插件的priority 398、version 0.1属于标准的日志类插件log阶段收集日志条目body_filter阶段负责采集响应体当开启include_resp_body时。属性详解以下属性表完整继承自 官方文档并与 插件源码中的 schema 定义 逐项核对名称类型必选项默认值有效值描述endpoint_addr废弃是ClickHouse 的endpoints单值已废弃请使用endpoint_addrs代替endpoint_addrsarray是ClickHouse 的endpoints数组例如[http://127.0.0.1:8123]databasestring是写入的数据库名logtablestring是写入的表名userstring是ClickHouse 用户名passwordstring是ClickHouse 密码timeoutinteger否3[1,...]发送请求的超时时间秒namestring否clickhouse loggerlogger 的唯一标识符若使用 Prometheus 监控 APISIX 指标该名称会以apisix_batch_process_entries指标导出ssl_verifyboolean否true[true, false]为true时校验 HTTPS 证书log_formatobject否以 JSON 键值对声明日志格式值部分仅支持字符串以$开头表示取 APISIX 变量 或 NGINX 内置变量include_req_bodyboolean否false[false, true]为true时记录请求体注意若请求体无法完全存放在内存中受 NGINX 限制将无法记录include_req_body_exprarray否在include_req_bodytrue时做过滤仅当表达式计算结果为true才记录请求体表达式语法基于 lua-resty-exprinclude_resp_bodyboolean否false[false, true]为true时记录响应体include_resp_body_exprarray否在include_resp_bodytrue时做过滤仅当表达式计算结果为true才记录响应体表达式语法基于 lua-resty-expr从源码看 schema 校验的细节在 clickhouse-logger.lua 的 schema 中有几个值得注意的实现细节二选一校验schema 使用oneOf约束endpoint_addr与endpoint_addrs二者必须且只能提供一个均需配合user、password、database、logtable。测试用例 t/plugin/clickhouse-logger.t 中专门验证了auth 配置缺失时返回value should match only one schema, but matches none的报错场景。密码加密存储schema 中声明了encrypt_fields {password}即password字段会被加密后存入 etcd详情参考 加密存储字段。HTTPS 相关检查check_schema阶段会调用core.utils.check_https检查endpoint_addrs是否为合法的 https 地址并调用check_tls_bool校验ssl_verify布尔值。写入协议与多端点随机选择从 send_http_data 实现 可以看到底层写入逻辑若配置了多个endpoint_addrs每次发送会用math.random(#conf.endpoint_addrs)随机挑选一个端点日志会随机分布到各个端点请求方式为POST请求体为INSERT INTO logtable FORMAT JSONEachRow 日志数据请求头携带X-ClickHouse-User、X-ClickHouse-Key、X-ClickHouse-Database以及Content-Type: application/json超时时间为conf.timeout * 1000毫秒若端点为https协议会执行 TLS 握手并根据ssl_verify决定是否校验证书未指定端口时 https 默认 443、http 默认 80若服务端返回状态码 400则视为写入失败并返回错误信息。批处理器批量聚合并写入该插件与大多数日志插件一样使用批处理器Batch Processor聚合条目、批量提交避免每条请求都触发一次网络写入。批处理器的实现位于 apisix/utils/batch-processor.luaclickhouse-logger 通过 batch-processor-manager.lua 复用。默认情况下批处理器每5秒inactive_timeout或队列中数据达到1000条batch_max_size时提交一次。完整的批处理器配置项如下可直接写在插件的配置中名称类型必选项默认值描述namestring否clickhouse logger批处理器唯一标识默认取插件namebatch_max_sizeinteger否1000每批最多日志条数达到后立即推送inactive_timeoutinteger否5刷新缓冲区最大间隔秒到达后无论条数多少都会推送buffer_durationinteger否60批次中最旧条目必须被处理的最长期限秒max_retry_countinteger否0失败后的最大重试次数retry_delayinteger否1失败后重试的延迟秒关于批处理器更完整的说明与使用示例可参考 批处理器文档。文档与源码均建议保持inactive_timeout小于buffer_duration以获得最佳刷新效果。从 log 阶段的实现 可以看到数据组装细节单条日志时编码为单个{}对象多条日志时逐条json.encode后用空格拼接成{} {}字符串正好对应 ClickHouse 的JSONEachRow格式写入函数执行失败时批处理器会依据max_retry_count与retry_delay进行重试超过重试上限后丢弃这些条目并打印错误日志。默认日志格式示例当未自定义log_format时写入 ClickHouse 的日志条目结构如下来自 官方文档示例{ response: { status: 200, size: 118, headers: { content-type: text/plain, connection: close, server: APISIX/3.7.0, content-length: 12 } }, client_ip: 127.0.0.1, upstream_latency: 3, apisix_latency: 98.999998092651, upstream: 127.0.0.1:1982, latency: 101.99999809265, server: { version: 3.7.0, hostname: localhost }, route_id: 1, start_time: 1704507612177, service_id: , request: { method: POST, querystring: { foo: unknown }, headers: { host: localhost, connection: close, content-length: 18 }, size: 110, uri: /hello?foounknown, url: http://localhost:1984/hello?foounknown } }字段生成逻辑可在 apisix/utils/log-util.lua 的get_full_log中溯源包括请求/响应头与体、URI、客户端 IP、route_id、service_id、latency/upstream_latency/apisix_latency三段耗时毫秒、start_time毫秒时间戳、server节点信息等。其中各延迟指标由latency_details_in_ms计算得出若upstream_response_time存在则拆分出上游耗时与 APISIX 自身耗时。配置插件元数据自定义全局日志格式clickhouse-logger支持通过插件元数据Plugin Metadata配置全局的log_format与 http-logger 插件行为一致名称类型必选项默认值描述log_formatobject否以 JSON 键值对声明日志格式值仅支持字符串以$开头表示取 APISIX 或 NGINX 变量。该配置全局生效一旦指定将对所有绑定clickhouse-logger的路由或服务生效首先从config.yaml中取出 Admin API 的 key 存入环境变量示例中yq解析 conf/config.yamladmin_key$(yq .deployment.admin.admin_key[0].key conf/config.yaml | sed s///g)然后通过 Admin API 配置插件元数据curl http://127.0.0.1:9180/apisix/admin/plugin_metadata/clickhouse-logger \ -H X-API-KEY: $admin_key -X PUT -d { log_format: { host: $host, timestamp: $time_iso8601, client_ip: $remote_addr } }自定义格式的解析实现在 log-util.lua 的 get_custom_format_log以$开头的值会被解析为变量引用并取自ctx.var其余值作为字符串常量直接输出解析结果会同时自动附加service_id与route_id。环境准备启动 ClickHouse 并建表使用 Docker 启动 ClickHousedocker run -d -p 8123:8123 -p 9000:9000 -p 9009:9009 --name some-clickhouse-server --ulimit nofile262144:262144 clickhouse/clickhouse-server其中8123为 HTTP 接口插件写入所用9000为原生 TCP 接口9009为集群内部通信接口。创建日志表在 ClickHouse 中创建一张用于存储日志的表示例库为default、表名为test字段需与自定义日志格式的键对应curl -X POST http://localhost:8123/ \ --data-binary CREATE TABLE default.test (host String, client_ip String, route_id String, service_id String, timestamp String, PRIMARY KEY(timestamp)) ENGINE MergeTree() --user default:提示如果使用默认未自定义日志格式建表字段应覆盖request、response、server、upstream、client_ip、route_id、service_id、start_time及各延迟字段等结构化的列ClickHouse 也支持将整条 JSON 存为 String 列可按业务需要设计表结构。启用插件通过 Admin API 在指定路由此处为uri: /hello上启用clickhouse-loggercurl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { plugins: { clickhouse-logger: { user: default, password: , database: default, logtable: test, endpoint_addrs: [http://127.0.0.1:8123] } }, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } }, uri: /hello }:::note 注意 如果配置多个endpoints日志将随机写入到各个endpoints对应源码中math_random随机选择逻辑。 :::若需要更精细的写入控制可在插件配置中叠加批处理器参数例如batch_max_size: 1000, inactive_timeout: 5, max_retry_count: 1如需记录请求/响应体可增加include_req_body: true、include_resp_body: true及对应的include_req_body_expr/include_resp_body_expr过滤表达式。测试插件向 APISIX 发起请求以产生一条访问日志curl -i http://127.0.0.1:9080/hello随后查询 ClickHouse 表中的数据curl http://localhost:8123/?queryselect%20*%20from%20default.test 127.0.0.1 127.0.0.1 1 2023-05-08T19:15:5305:30输出依次对应建表时的字段host、client_ip、route_id、service_id、timestamp说明日志已成功落库。仓库测试用例 t/plugin/clickhouse-logger.t 覆盖了完整配置校验、基本配置校验、缺失认证字段报错、单端点/多端点插件启用以及真实请求命中路由等场景可作为验证插件行为的参考。删除插件如需移除该插件只需将路由配置中的plugins置空APISIX 会自动热加载配置无需重启服务curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { methods: [GET], uri: /hello, plugins: {}, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } } }小结clickhouse-logger将 APISIX 的访问日志以JSONEachRow格式批量写入 ClickHouse通过批处理器聚合日志以降低写入频率通过插件元数据或插件配置灵活定制日志字段通过多端点随机写入实现简单的负载分散并通过encrypt_fields保障密码在 etcd 中的加密存储。结合本仓库的 插件源码、批处理器实现 与 测试用例开发者可以快速定位问题也可以参照该插件的写法实现自己的日志类插件。【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表