APISIX udp-logger 完整跑通:15 分钟把访问日志打到自建 UDP 端 APISIX udp-logger 完整跑通15 分钟把访问日志打到自建 UDP 端【免费下载链接】apisixThe Cloud-Native API Gateway and AI Gateway项目地址: https://gitcode.com/gh_mirrors/api/apisixAPISIX udp-logger 是日志类插件它把每个请求的访问日志聚合成 JSON 条目用单个 UDP 数据报打到目标 UDP 服务自建采集器、Vector、监控汇聚端。读完这篇你能把 udp-logger 绑定到一条路由、在 UDP 端亲眼看到日志落地并调好批量节奏与积压上限。udp-logger 适用性速判选不选 udp-logger看下面 4 个维度判断维度结论一句话备注日志通道目标是 UDP 端口就用它HTTP 端点换 http-logger该插件只发 UDP 数据报不发 TCP丢包容忍UDP 无重传日志可能丢、可能乱序容忍丢部分日志才适合要求必达不选协议层HTTP 子系统开箱即用默认日志stream 必须配 log_format四层代理场景要显式声明日志格式典型汇聚端自建 python/nc 监听端、Vector、Fluent Bit 的 UDP 接收先用nc -u host port验证可达udp-logger 配置一览参数全表参数写在路由或 Service 的plugins.udp-logger节点下。标*的字段由公共日志工具与批处理器注入schema 在 apisix/plugins/udp-logger.lua 中经批处理器管理器包装所有基于批处理器的 logger 插件共享参数类型必填默认说明hoststring是UDP 目标的 IP 或主机名portinteger是目标 UDP 端口timeoutinteger否3发送超时单位秒见踩坑第 3 条log_formatobject否自定义日志结构$引用变量namestring否udp logger批处理器标识会进监控指标include_req_bodyboolean否false记录请求体include_req_body_exprarray否表达式为 true 才记请求体include_resp_bodyboolean否false记录响应体include_resp_body_exprarray否表达式为 true 才记响应体log_format_extra *object否给默认日志追加字段不覆盖max_req_body_bytes *integer否524288请求体采集上限512 KiBmax_resp_body_bytes *integer否524288响应体采集上限512 KiBbatch_max_size *integer否1000条数达标即推送1逐条发送inactive_timeout *integer否5最长等待推送的秒数buffer_duration *integer否60批中最老条目的最长滞留秒数max_retry_count *integer否0发送失败的最大重试次数retry_delay *integer否1重试间隔秒数max_pending_entries *integer否8192积压上限经插件元数据配置最小可运行配置放进路由的 plugins 节点{ plugins: { udp-logger: { host: 127.0.0.1, port: 3000, batch_max_size: 1 } } }batch_max_size: 1表示每条请求都立刻独立发送验证链路最快。从 0 到验证下发路由打一条请求看 UDP 端拿到 Admin Key后续所有 Admin API 操作都要带鉴权。standalone 部署可直接从配置文件读出admin_key$(yq .deployment.admin.admin_key[0].key conf/config.yaml | sed s///g) # ← 你应该看到无报错echo $admin_key 有值本地起 UDP 监听端下发路由并绑定 udp-logger先起一个 UDP 接收端再下发一条/hello路由并把插件绑上去python3 -c import socket s socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind((127.0.0.1, 3000)) print(UDP listening on 127.0.0.1:3000) while True: print(s.recv(65535)) curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { plugins: { udp-logger: { host: 127.0.0.1, port: 3000, batch_max_size: 1 } }, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } }, uri: /hello } # ← 你应该看到{action:create,id:1,...}打一条请求看 UDP 端收到什么从网关 9080 端口打一条请求curl -i http://127.0.0.1:9080/hello # ← 你应该看到HTTP/1.1 200 OK响应体是 hello, world几秒内 python 监听端会打印出一条完整 JSON。因为batch_max_size 1这条日志以单个对象编码而不是数组b{request:{method:GET,url:http://127.0.0.1:9080/hello,headers:{...}}, response:{status:200,size:12},route_id:1, upstream:127.0.0.1:1980,latency:3.5,upstream_latency:2.1,apisix_latency:1.4} # ← 你应该看到带 route_id、latency 等字段的完整条目这个默认结构覆盖请求方法与头、URI、响应状态与头、server 版本、route_id、client_ip 和 latency / upstream_latency / apisix_latency 三层耗时若路由匹配失败service_id 会退化为请求的 host。不想要了怎么删把 plugins 节点置空即可停止投递热更新立即生效无需重启curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { plugins: {}, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } }, uri: /hello } # ← 你应该看到{action:update,id:1,...}监听端不再收到新条目udp-logger 排错5 个常见坑与边界症状下发报 400提示property host is required→根因host与port是仅有的两个必填项缺一个就被拒 →处置先核对字段名与拼写timeout传字符串10会报wrong type: expected integer, got stringlog_format传字符串同样报expected object, got string。症状UDP 端收不到日志error.log 出现failed to connect to UDP server: host[x.x.x.x] port[2000]→根因目标地址/端口配错或对方没有监听UDP 没有握手这一步的失败其实出在地址解析与绑定阶段 →处置用ss -ulnp确认本地端口在监听再确认远端可达仓库端到端测试 t/plugin/udp-logger.t 覆盖了从必填校验到不可达地址的完整断言。症状timeout行为与旧文档表格写默认 1000对不上 →根因当前源码 schema 默认是3发送函数执行sock:settimeout(conf.timeout * 1000)参数单位是秒 →处置以实际运行版本源码为准沿用旧毫秒语义的存量配置要除以 1000 换算。症状汇聚端变慢时 worker 内存冲到几百 MB 甚至 GB 级 →根因积压受元数据max_pending_entries默认 8192封顶单条大小取决于是否采集 body超限后新条目直接丢弃error.log 每秒最多汇总一条→处置关闭 body 采集或用max_req_body_bytes/max_resp_body_bytes封顶调大batch_max_size时正常积压同步上涨需联动调大上限。症状stream四层路由不出默认日志error.log 出现log_format is not set→根因默认完整日志依赖请求/响应头与状态码只适用于 HTTP 子系统 →处置四层场景必须显式配置log_format可用 APISIX 变量清单里的字段拼装。udp-logger 调优与进阶批处理节奏、积压内存与 $ 变量批处理节奏。推送时机由batch_max_size条数与inactive_timeout秒共同决定先到先触发buffer_duration默认 60 秒是强制兜底保证最老条目不会被无限滞留发送失败按max_retry_count/retry_delay重试重试耗尽的批次连同剩余条目进入丢弃统计语义完整实现见 apisix/utils/batch-processor.lua。积压与内存。以默认参数实测日志端接受连接但不响应、8192 积压上限worker 内存峰值大致如下每请求采集的 bodyworker 内存峰值不采集 body~40 MB1 KB 请求 1 KB 响应~100 MB4 KB 请求 4 KB 响应~250 MB16 KB 请求 16 KB 响应~840 MB规律很直接body 越大max_pending_entries越要调小batch_max_size调大意味着常态积压变高上限要同步放大。自定义 log_format 与 $ 变量。$开头的字符串解析为变量引用$host取ctx.var.host$request_body是特殊键按max_req_body_bytes上限读请求体纯字符串原样输出嵌套对象递归展开深度到 5 层即截断并记 warn解析结果走 lrucacheTTL 300 秒不会每请求重复编译。自定义格式会自动追加route_id/service_id。插件元数据还能设全局log_format对所有绑定 udp-logger 的路由生效与max_pending_entriescurl http://127.0.0.1:9180/apisix/admin/plugin_metadata/udp-logger \ -H X-API-KEY: $admin_key -X PUT -d { log_format: { host: $host, timestamp: $time_iso8601, request: { method: $request_method, uri: $request_uri }, response: { status: $status } }, max_pending_entries: 2048 } # ← 你应该看到{action:create,...}格式即时生效无需重启批处理编码细节。flush 回调触发时batch_max_size 1把单条编码成对象否则整批编码成数组local func function(entries, batch_max_size) local data, err if batch_max_size 1 then data, err core.json.encode(entries[1]) -- encode as single {} else data, err core.json.encode(entries) -- encode as array [{}] end return send_udp_data(conf, data) endudp-logger 的边界很清晰可丢包、无排序保证只适合容忍少量丢失的日志与遥测场景要求必达就换 http-logger 或 kafka-logger。下一步读 Batch-Processor 文档把retry_delay、buffer_duration的完整语义吃透。【免费下载链接】apisixThe Cloud-Native API Gateway and AI Gateway项目地址: https://gitcode.com/gh_mirrors/api/apisix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考