本文将探讨如何使用 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 查询的样子。
GET yf-test-1shard/_search
{
"query": {
"wildcard": {
"path.keyword": {
"value": "/a*"
}
}
}
}
上面的查询,会查询 path 字段,所有以 /a 开头的文档。
第一步:我们可确定关键字是 wildcard,为了进一步限制是 wildcard 查询里的情况,我们可将关键字确定为 wildcard":
,因为有时候查询 url 里会有 expand_wildcards 字样。
第二步:编辑 INFINI Gateway 默认配置文件,增加 context_filter 匹配规则。
- name: default_flow
filter:
- context_filter:
context: _ctx.request.to_string
message: "Request blocked. Reason: Forbidden. Please contact the administrator at 010-111111."
status: 403
action: deny
must_not:
contain:
- 'wildcard":'
通过上面的修改,我们在 INFINI Gatway 的默认处理流程开头添加了 context_filter 过滤器,阻止查询请求种带关键字 wildcard":
的查询,并返回消息"Request blocked. Reason: Forbidden. Please contact the administrator at 010-111111."
第三步,测试 wildcard 请求能否被阻断。
可以看到,INFINI Gateway 成功阻止了 wildcard 查询,并返回了我们定义的信息。通过此方法,我们可以阻断高消耗类查询被发送到 ES 集群,避免引发集群性能问题。对业务上合理的需求,我们可以进一步沟通,确定合理的方案。
关于极限网关(INFINI Gateway)
INFINI Gateway 是一个面向搜索场景的高性能数据网关,所有请求都经过网关处理后再转发到后端的搜索业务集群。基于 INFINI Gateway,可以实现索引级别的限速限流、常见查询的缓存加速、查询请求的审计、查询结果的动态修改等等。
开源地址:https://github.com/infinilabs/gateway,如有相关问题或建议,欢迎提交 PR 或 Issue !
作者:杨帆,极限科技(INFINI Labs)高级解决方案架构师、《老杨玩搜索》栏目 B 站 UP 主,拥有十余年金融行业服务工作经验,熟悉 Linux、数据库、网络等领域。目前主要从事 Easysearch、Elasticsearch 等搜索引擎的技术支持工作,服务国内私有化部署的客户。
本文地址:http://elasticsearch.cn/article/15395