凌晨导出任务跑到十几批开始报 Trying to create too many scroll contexts. Must be less than or equal to: [500]。节点堆内存从 40% 涨到 78%,重启之后才降下来。乍看像缓存或者权限的锅,追下去往往不是。
GET _nodes/stats/indices/search?filter_path=**.open_contexts
DELETE _search/scroll
{"scroll_id": ["DXF1ZXJ5QW5kRmV0Y2gBAAAA..."]}
追下去是这么回事:每个 scroll 都会在协调节点保留一份快照上下文,默认上限 500 个,靠 clear 或超时释放。导出代码中途抛异常,clear 没放进 finally,上下文就一直挂着。挂着的上下文还占着段文件,堆和磁盘一起涨。
「scroll 上下文泄漏」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
偶发问题先统计频率,一小时几次和一天一次,查法完全不同。改完顺手把文档补一句,省得下次自己重新推一遍。
监控和日志的时间要对上,时区不一致会多绕很大一圈。
具体做法是,把 clear 放进 finally 保证异常路径也执行;scroll 请求带明确的 keep_alive 比如 2m 别写 30m;用 PIT 加 search_after 替代长 scroll 减少常驻上下文;已经在跑的集群先看 open_contexts 数量。
验收就看一点,open_contexts 从 480 回落到个位数,导出任务再跑不再报 500。
