【ElasticSearch】基于插件模式实现ES集群状态监控、查询监控与采样
导语:ES自6.0+版本以来,已经开源了Kibana、Xpack等组件用于实时监控集群内存、网络、磁盘等消耗趋势数据,但部分功能如实时告警还处于商业化阶段,而在实际生产环境中,业务方关注的指标可能比较精细化,例如需要查看特定时间段查询返空或失败的具体查询语句、集群分片与节点监控及告警等,所以这些情况下,监控场景需要结合插件做定制化开发。
一、 业务需求背景
针对集群做如下监控相关功能的定制化开发:
(1) 以业务名、服务IP、集群名等多个维度上报查询时耗数据,并对时耗数据分级管理;
(2) 针对查询badcase做采样并输出到自定义日志中;
(3) 以请求IP、服务IP、集群名等维度上报集群状态信息
业务方希望自定义这些关键字权重,以这些关键字分数之和作为文章总分数,按指定排序方式召回文章。
二、查询流程源码分析
采集与上报监控数据之前,需要先了解ES中一次查询的详细流程。ES查询主要包括以下几个关键阶段:
- RestRequest阶段:通过netty接收HTTP或TCP查询请求并转发给具体Handler,BaseRestHandler抽象类实现了RestHandler接口,执行BaseRestHandler中的handleRequest方法:wrappedHandler.handleRequest(request, channel, client)
- SearchRequest阶段:通过RestSearchAction中prepareRequest方法将RestRequest对象转化为SearchRequest对象,执行NodeClient的search方法:client.search(searchRequest, new RestStatusToXContentListener<>(channel))
- SearchAction阶段:节点客户端处理SearchAction,执行方法:execute(SearchAction.INSTANCE, request, listener),通过ActionListener类型监听结果
- TransportAction阶段:生成类型为"transport"的SearchAction,异步调度QUERY_THEN_FETCH查询任务,通过ActionListener响应执行结果
- 后续结果为底层分阶段调度,可获取QUERY_THEN_FETCH各阶段查询时耗,不作关注
三、具体实现步骤
由上述源码分析可得,与查询相关的关键对象为RestHandler与ActionListener,前者可用于截获或校验RestRequest,后者可用于监听SearchAction或其他类型Action的响应时耗并做相应处理。
1. 通过实现ActionPlugin自定义Action过滤器
public class MonitorServerPlugin extends Plugin implements SearchPlugin, ActionPlugin {
public static final String NAME = "monitor-plugin";
public static final String REST_HANDLER = ".RestSearchAction";
public String name() {
return NAME;
}
public String description() {
return NAME