使用 INFINI Gateway 保护 Elasticsearch 集群之阻断不合理的查询

本文将探讨如何使用 INFINI Gateway 阻止不合理的查询发送到 Elasticsearch,此方法同样适用于 Opensearch 和 Easysearch 。
在以往处理 Elasticsearch OOM(内存溢出)问题的经验中,我们发现许多案例是由于查询操作导致节点出现 OOM 的情况。经过调查,这些案例主要分为两类:一类是由于查询吞吐量超出了集群的处理能力,另一类则是在执行某些不合理的查询时触发了 OOM。
具体来说:
查询吞吐量过高:当查询请求的频率或复杂度超过了集群的处理能力时,可能会导致节点内存耗尽,从而引发 OOM。
执行不合理查询:某些特殊类型的查询(例如涉及大量嵌套、深度分页或复杂的聚合操作)可能需要大量的内存资源,在执行过程中也可能导致 OOM。
通过识别并优化这些查询模式,可以有效减少 OOM 事件的发生。针对查询吞吐量过高的情况,可以参考之前的文章来管理查询吞吐。接下来的内容将介绍如何阻挡不合理查询,保护集群稳定。
不合理查询
不合理查询是指那些消耗过多系统资源(如 CPU、内存)、设计复杂、执行时间过长或需要大量计算资源的查询。这类查询不仅会导致高负载和资源耗尽,影响整个集群的稳定性和响应速度,还可能对用户体验产生负面影响。
典型的不合理查询包括但不限于:
嵌套聚合查询
使用复杂的正则表达式进行模糊匹配
深度分页查询(如 from: 10000, size: 10)
脚本查询(Script Query)
大规模嵌套聚合查询
为了防止这些查询对 Elasticsearch 集群造成影响,我们可以使用 INFINI Gateway 对这些查询进行阻断。
请求上下文
INFINI Gateway 运行环境中有非常多的信息可被利用,而请求上下文就是访问这些信息的入口。如请求来源、请求体信息等,都可使用关键字 _ctx 作为前缀访问相应的上下文信息。
HTTP 请求内置的 _ctx 上下文对象主要包括如下:

更多的上下文信息请访问文档。
context_filter
Context Filter 是 INFINI Gateway 提供的一种在线过滤器,能够根据请求上下文来过滤流量。通过定义一组匹配规则,可以灵活地对流量进行筛选。该过滤器支持多种匹配模式,包括:
前缀匹配
后缀匹配
模糊匹配
正则匹配
对于匹配到的请求,可以直接阻断(拒绝)并返回自定义的消息。因此,关键点就是要明确不合理请求的关键字信息。
使用步骤
确定关键字信息:确定特殊查询请求中的关键特征或关键字。
配置匹配规则:在 context_filter 中定义相应的匹配规则,选择合适的匹配模式(如前缀、后缀、模糊或正则匹配)。
阻断请求:一旦匹配到这些关键字,INFINI Gateway 将自动阻断请求并返回指定的消息。
更多详细内容,请参阅相关 文档。
举个例子
阻止 wildcard 查询(模糊匹配查询),我们先看一个 wildcard 查询的样子。
上面的查询,会查询 path 字段,所有以 /a 开头的文档。

第一步:我们可确定关键字是 wildcard,为了进一步限制是 wildcard 查询里的情况,我们可将关键字确定为 wildcard":
,因为有时候查询 url 里会有 expand_wildcards 字样。
第二步:编辑 INFINI Gateway 默认配置文件,增加 context_filter 匹配规则。
通过上面的修改,我们在 INFINI Gatway 的默认处理流程开头添加了 context_filter 过滤器,阻止查询请求种带关键字 wildcard":
的查询,并返回消息"Request blocked. Reason: Forbidden. Please contact the administrator at 010-111111."
第三步,测试 wildcard 请求能否被阻断。

可以看到,INFINI Gateway 成功阻止了 wildcard 查询,并返回了我们定义的信息。通过此方法,我们可以阻断高消耗类查询被发送到 ES 集群,避免引发集群性能问题。对业务上合理的需求,我们可以进一步沟通,确定合理的方案。
版权声明: 本文为 InfoQ 作者【极限实验室】的原创文章。
原文链接:【http://xie.infoq.cn/article/b697b6fb667e760e8ced58d1d】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论