【升职加薪秘籍】我在服务监控方面的实践(8)-elasticsearch 性能监控与分析手段

发布时间 2023-08-30 17:47:29作者: 蓝胖子的编程梦

大家好,我是蓝胖子,之前讲了mysql,redis中间件的监控,今天我们再来看看另一个基础组件elasticsearch,如何对它进行监控,当你思考如何对一个组件进行监控时,四大黄金指标会告诉你答案,我们同样会从四大黄金指标给出的维度进行分析。

针对es做的性能分析,用四大黄金指标原则,我们可以做出如下的分析

Pasted image 20230804141859.png

这些指标能够方便我们快速搭建起一套监控面板来对es进行监控,下面我们来看看具体应该如何做。

流量,延迟

首先,我们来看下在流量这个维度上,我们是对es集群qps指标进行监控,也就是各个索引每秒访问的次数。这个其实可以在kibana上通过monitor模块进行监控,不过因为我们线上都是采用prometheus 进行组件监控,为了让监控报警系统架构比较统一,尽可能采用少的组件,还是决定沿用prometheus+grafana的形式进行监控。

对于延迟来讲,可以按索引维度监控索引的操作时间p99分位数,这两个维度的监控可以采用对elasticsearch client 客户端进行埋点的方式来监控,并且当前es已经支持sql格式的的查询语句,即使你的es版本比较旧,依然能找到很多现成的库将sql格式的查询语句转换为es的DSL格式查询语句。

所以,完全可以采用和【升职加薪秘籍】我在服务监控方面的实践(6)-业务维度的mysql监控 一节中类似的方式,对sql语句进行解析,按sql表(在es中是索引名)维度对qps,查询时长进行监控。建立完相关指标和埋点后,用prometheus进行收集,grafana面板进行显示即可,步骤可以说和mysql那一节里一模一样。

在延迟监控方面,一般也会启用es的慢日志记录,这样可以针对具体的慢查询做优化。以下是设置慢日志的语句。

PUT /_all/_settings
{
"index.search.slowlog.threshold.query.warn": "600ms",
    "index.search.slowlog.threshold.query.info": "400ms",
    "index.search.slowlog.threshold.query.debug": "300ms",
    "index.search.slowlog.threshold.query.trace": "200ms",
    "index.search.slowlog.threshold.fetch.warn": "500ms",
    "index.search.slowlog.threshold.fetch.info": "400ms",
    "index.search.slowlog.threshold.fetch.debug": "300ms",
    "index.search.slowlog.threshold.fetch.trace": "200ms",
    "index.search.slowlog.level": "trace"
 }

错误数

接着,再来看下在错误数这个维度上的指标监控,针对es而言,错误主要是查询错误,比如很常见的429这类型的错误,我们同样可以在客户端库进行埋点,对执行查询语句时的错误数以及具体错误进行监控。

注意下,我们的流量,延迟,错误数都是采用客户端库埋点的方式进行统计的,这样的好处是让监控指标能够更好的和业务建立联系(毕竟是索引维度上的监控)。实际上,任何一个组件,你都可以采取类似的客户端埋点的方式对这3个指标维度进行监控。

饱和度

接着,再来看下如何监控es的饱和度,饱和度指集群各种资源的饱和状态,除了正常监控cpu,内存,磁盘空间,网络带宽外,特别的针对于es而言,还有各种断路器和线程池队列的监控。

在es中,有各种类型的断路器,它们主要是为了避免es内存溢出而设计的一套机制。在执行某种类型的操作时,会查看对应类型的断路器内存预留量,以及评估当前操作需要消耗的内存,如果超过了内存预留量,则终止本次操作,这个时候客户端会得到429错误。所以,断路器的内存预留量,也是饱和度的一种体现。

在来看看es中的线程池的监控,es中,有各种类型的线程池,它们分别对应各种不同的操作,比如search,write,refresh,同时线程池会分配一个队列, 如果某种类型的线程池队列满了,那么它将拒绝新的此类型的操作,客户端会得到429错误。所以线程池的大小已经队列长度也是es饱和度的一种体现。

对于断路器和es队列,cpu,内存等等的监控都可以用elasticsearch exporter,prometheus到时候收集exporter的指标,用grafana进行展示即可,而elasticsearch exporter的dashboard目前已经有很多开源的方案,选择一个就可以轻松导入。

使用prometheus 的监控,一般就是利用各种类型的exporter ,通过exporter收集对应的指标数据。elasticsearch现有的开源方案就有elasticsearch exporter。

性能api

在看了前面在四大黄金指标原则下的监控,我们能够去衡量一个es集群当前的服务质量,但这还是不够的,比如es的cpu突然飙高,这个时候如果要想去定位是哪些查询语句导致的,仅仅通过四大黄金指标原则就比较困难。

es为我们提供了api能够查看当前集群占用cpu高的线程堆栈,方便定位问题。

GET /_nodes/hot_threads

同时es也提供了task api对es中执行的任务进行监控,每个查询请求也被当成一个任务在执行。

GET /_tasks?detailed=true

"dQ9dt0POQMuYk4b1irs5bQ:15752986287" : {
          "node" : "dQ9dt0POQMuYk4b1irs5bQ",
          "id" : 15752986287,
          "type" : "transport",
          "action" : "indices:data/read/search",
          "description" : """indices[zdisk_item], types[], search_type[QUERY_THEN_FETCH], source[{"from":0,"size":20,"query":{"bool":{"filter":[{"term":{"pid.term":{"value":21560540,"boost":1.0}}}],"must_not":[{"term":{"tpid.term":{"value":"-1","boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}},"sort":[{"type_sort":{"order":"desc"}},{"name_sort":{"order":"asc"}}]}]""",
          "start_time_in_millis" : 1691446262166,
          "running_time_in_nanos" : 25457435,
          "cancellable" : true,
          "headers" : { }
        },

返回结果中能够包含执行的查询语句已经任务运行的时间,我们可以在cpu或者内存压力比较大时,通过task api发现是哪些查询耗时较长。

保留问题现场

你可以发现,通过hot_threads api 和task api能够比较容易发现问题所在,但问题发生时并不一定能在现场执行它们,如果问题发生时,能够自动执行它们并把结果保存下来就好了。这样能为之后的问题排查提供证据。

我们可以在grafana上,通过为cpu,内存监控面板设置报警策略,比如达到某个阈值就通过webhook策略调用自己写的一个程序,而这个程序的逻辑便是执行hot_threads api 和task api并将结果保留下来,这样就达到了保留问题现场的目的。

总结

通过这一节,我们利用四大黄金指标原则分析了如何对es集群进行了监控,你可以发现,即使你对组件没有很深入的了解,四大黄金指标原则依然能够很好的指导你如何建立监控维度。相信通过这一节,你会更加深入的理解四大黄金指标原则。

并且,我们对elasticsearch的监控依然没有脱离定位问题这一目的,我们通过索引维度的qps,延迟监控,保留问题现场来更好的定位问题,注意,监控不仅要发现问题,还要定位问题,这也是我对创建什么样的监控指标所遵循原则,只有定位到了问题才能快速的解决问题。