用libcurl批量发\_bulk请求比单条插入快10倍以上,因避免HTTP连接开销;需启用TCP复用、控制每批500–2000条、严格遵循action metadata格式、索引名按日+ILM策略管理、预定义字段映射、按error类型分流处理失败。

用 libcurl 批量发 _bulk 请求比单条插入快 10 倍以上
单条 PUT 或 POST 写入 Elasticsearch 会产生大量 HTTP 连接开销,尤其在日志高频采集场景下,吞吐直接卡死在几百 QPS。必须走 _bulk 接口——它把多条操作(index、create)序列化成一个 HTTP body,一次请求处理数百甚至上千文档。
实操建议:
立即学习“C++免费学习笔记(深入)”;
-
libcurl启用连接复用:设置CURLOPT_TCP_KEEPALIVE和CURLOPT_FORBID_REUSE为0L,避免每次_bulk都重建 TCP 连接 - 每批控制在 500–2000 条之间:太小起不到批量效果;太大容易触发 ES 的
http.max_content_length(默认 100MB)或 OOM - 每条文档前必须加 action metadata 行(如
{ "index": { "_index": "customs-log-202406" } }),且 metadata 行与文档体之间必须有换行符\n,否则 ES 返回400 Bad Request - 用
CURLOPT_POSTFIELDS直接传 raw string,别用CURLOPT_POSTFIELDSIZE手动算长度——C++std::string含 \0 时会截断
索引名带日期后缀 + ILM 策略才能扛住海关日志的写入洪峰
海关日志是典型的时序数据,按天建索引(如 customs-log-20240615)不是为了“好看”,而是让 ES 分片压力分散、删除旧数据不阻塞写入、以及配合 ILM 自动滚动和冷热分离。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 写入前用
strftime生成当日索引名,拼进_bulk的 action 行里,别硬编码固定索引名 - 提前用 API 创建 ILM 策略,例如 7 天 rollover + 30 天 delete,避免手动删索引引发主节点压力 spike
- 注意
rollover触发条件:别只看时间(max_age),加max_docs: 50000000防止单日日志突增撑爆分片 - 如果用
data stream,确保日志文档含@timestamp字段且为date类型,否则写入失败报invalid date format
字段映射必须预定义,否则动态 mapping 会让集群变慢甚至挂掉
海关日志字段多(报关单号、HS 编码、运输工具 ID、申报时间等),且部分字段值长而杂(如 JSON 格式备注)。ES 默认开启 dynamic mapping,遇到新字段就自动推断类型,会导致:
- mapping 膨胀,单个索引 mapping 超过 512MB 时,主节点拒绝更新,写入全挂
- 字符串被误判为
text并建全文索引,浪费 CPU 和磁盘,且无法用于聚合 -
HSCode这类本该是 keyword 的字段变成 text,后续做 term 查询或 cardinality 聚合直接不准
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
PUT /customs-log-*提前定义 template,强制"HSCode": { "type": "keyword" }、"declareTime": { "type": "date", "format": "strict_date_optional_time||epoch_millis" } - 所有可能含中文或特殊符号的字段(如
goodsName)显式设"index": false,除非真要搜全文 - 对超长字段(如报关单 XML 原文)用
"enabled": false,避免解析失败或 mapping 溢出
写入失败时别简单重试,要按 error 类型分流处理
_bulk 响应体里每个操作都带 status 和 error,常见错误不能一概而论:
-
"status": 429:ES 正在限流,说明 bulk 太大或集群资源不足,应退避重试(指数退避),而非立刻重发 -
"status": 400+"reason": "failed to parse field [declareTime] of type [date]":数据格式脏,需清洗后丢进死信队列(DLQ),别反复塞进 bulk -
"status": 404+"reason": "no such index":索引名拼错或 template 没生效,该报警,不该重试 -
"status": 503:ES 集群不可用,检查_cat/allocation?v是否有 unassigned shards
关键点:解析 bulk 响应必须遍历 items 数组,逐个判断 error 字段是否存在,不能只看整体 errors: true 就全盘回滚。
海关日志这种强合规场景,字段格式错一条都可能影响通关分析,批量写入的健壮性不在“快”,而在“错得明明白白”。


















