elasticsearch 官方监控文档 老版但很有用

https://zhaoyanblog.com/page/1?s=elasticsearch

 

监控每个节点(jvm部分)

操作系统和进程部分

操作系统和进程部分的含义是很清楚的,这里不会描述的很详细。他们列出了基本的资源统计,例如CPU和负载。操作系统部分描述了整个操作系统的情况,进程部分只是描述了Elasticsearch的JVM进程的使用情况。

这显然是很有用的统计, 但是往往会被忽视,一些统计包括如下部分:

>CPU
>负载
>内存使用情况
>swap使用情况
>打开文件句柄数

JVM部分
jvm部分包含一些有关于运行elasticsearch的jvm进程的关键信息。最重要的是,它包含了垃圾回收方面的细节,这对你的elasticsearch的集群的稳定性有很大影响。

>垃圾收集(GC)入门

在我们描述这个之前,很有必要先介绍下GC以及它对elasticsearch的影响。如果你对jvm中的GC很熟悉,可以跳过这一章。

java是一个自己进行垃圾回收的语言,也就是说程序员不需要主动管理内存的分配和释放。程序员只要专心写自己的代码,java虚拟机会管理根据需要分配内存的过程,然后当内存不再使用的时候,它自己会去释放。

当内存被分配给JVM进程,它会被分配成一个叫堆的大块区域。JVM会把这个堆分成两组,叫做“代”:

年轻代(或者伊甸园)

新实例化的对象就在这里分配空间,年轻代的空间通常很小,大约100MB-500MB。年轻代包含两个幸存者区域

老年代

存储那些老的对象的区域。这些对象是长期存在,并且持续很长时间。老年代通常比年轻代大很多。你可以看到elasticsearch节点的老年代可能大到30GB

当一个对象被实例化后,它会被放置到年轻代,当年轻代的空间满了,一个年轻代的垃圾回收就启动了。那些仍然存活的对象就会被移动到其中一个幸存者区域。而死了的对象就会被清除了。如果一个对象在年轻代中经历了多次GC仍然幸存,那它将被晋升到老年代。

类似的过程也发生在老年代,当老年代的空间越来越满了,一个垃圾回收就启动了,同时死了对象会被清除。

天下没有免费的午餐,年轻代和老年代的垃圾回收都包含一个“stop-the-world”的阶段。在这个时间内,JVM会停止程序的执行,进行对象的标记和收集,在这个stop-the-world的阶段,没有任何事情发生,请求不会被处理,ping不会被会回应。shards不会再进行迁移。整个世界真的停止了。

对于年轻代这不是一个问题,因为它很小,GC执行的很快。但是对于大一点的老年代,缓慢的GC意味着1s甚至15s的停顿,这对于一个服务器软件来说是不可接受的。

垃圾回收在JVM是很复杂的算法,为了减少停顿做了很多的工作。同时Elasticsearch很努力适应GC,比如通过内部对象的重用,利用网络缓冲区,并挺贵一些特征值例如文档的数量。但是GC的频率和长短是需要你特别留意的信息,因为它是集群不稳定的头号元凶。

如果一个集群经常性的发生长时间GC,那么你的集群一定内存不足并且负载特别高。这些长时间GC会导致节点周期性的脱离集群。这种不稳定会导致分片数据不断的重新生成,以保证集群内的平衡以及足够的分片数量。这会增加网络贷款和磁盘IO,同时你的集群还要承担进行正常的索引数据和查询。

简而言之,长时间的GC是很糟糕的,需要尽可能的减少。

因为GC对Elasticsearch如此重要,你必须对node stats的API显示的这个部分特别熟悉才行。

"jvm": {
	"timestamp": 1408556438203,
	"uptime_in_millis": 14457,
	"mem": {
	   "heap_used_in_bytes": 457252160,
	   "heap_used_percent": 44,
	   "heap_committed_in_bytes": 1038876672,
	   "heap_max_in_bytes": 1038876672,
	   "non_heap_used_in_bytes": 38680680,
	   "non_heap_committed_in_bytes": 38993920,

jvm部分首先列出的是有关堆内存使用情况的一般情况,你可以看到多少heap被用到,有多少可以被使用(已经分配了线程),还有堆内存最大可以长到多少。理想情况下heap_committed_in_bytes应该和heap_max_in_bytes相同,如果被分配的堆较小,那JVM将会不得不调整堆的大小,这个过程代价是很高的。如果你的这两个值是不同的,请看《Heap: Sizing and Swapping》章节,确认你配置的是否正确。

heap_used_percent 是你必须盯着看的一个有用的参数。Elasticsearch配置的是当堆使用到75%的时候进行GC,如果你的节点总是大约75%,那你节点正在承受内存方面的压力,这是一个告警,预示着你不久就会出现慢GC。

如果你的heap使用率一直在85%以上,那你有麻烦了,90-95%的概率会因为10-30s的GC 发生性能问题,这还是好的,最坏的就是发生内存溢出。

"pools": {
      "young": {
         "used_in_bytes": 138467752,
         "max_in_bytes": 279183360,
         "peak_used_in_bytes": 279183360,
         "peak_max_in_bytes": 279183360
      },
      "survivor": {
         "used_in_bytes": 34865152,
         "max_in_bytes": 34865152,
         "peak_used_in_bytes": 34865152,
         "peak_max_in_bytes": 34865152
      },
      "old": {
         "used_in_bytes": 283919256,
         "max_in_bytes": 724828160,
         "peak_used_in_bytes": 283919256,
         "peak_max_in_bytes": 724828160
      }
   }
},

young, survivor, and old sections 显示了每个代在GC中的使用情况,供你分析。这些数据方便你看到他们的相对大小,但是对于你调查问题往往不是很重要。

gc": {
   "collectors": {
      "young": {
         "collection_count": 13,
         "collection_time_in_millis": 923
      },
      "old": {
         "collection_count": 0,
         "collection_time_in_millis": 0
      }
   }
}

gc区域显示的GC的次数和时间,包括年轻代和老年代。大部分时间,你可以忽略关于年轻代的手机次数,这个次数往往很大,这是很正常的。

相反,老年代的GC应该少一点,collection_time_in_millis也要小。这是个累计数字,很难给你一个你应该担心时候的数字(举个例子,一个节点运行了一年,可能有很多次GC,但是这个节点却很健康稳定)。这也是一些工具例如Maverl特别有用的原因。多长时间内的GC次数是个很重要的考虑因素。

花在GC上的时间也很重要,例如,在索引数据的时候会产生一定量的内存垃圾,这很正常,会让GC不时的发生。这些GC通常都是很快的,对节点也没有多少英雄。年轻代只需要一两毫秒。老年代可能需要几百毫秒。这和十秒级的GC是很大不同的。

我们最佳的建议是周期性的收集GC的个数和时间(或者使用Marverl) 并且留意频繁GC,你也可以打开慢GC日志,记录在日志里。

 

ThreadPool部分

Elasticsearch 内部使用了线程池,通过这些线程池之间的合作完成工作,在需要时传递工作。一般来说你不需要调整和优化线程池。但是有时候你看着这些线程池的状态,对你掌握你的集群行为是很有帮助的。

这有十几个线程池,他们的格式都是类似的:

"index": {
     "threads": 1,
     "queue": 0,
     "active": 0,
     "rejected": 0,
     "largest": 1,
     "completed": 1
  }

每个线程都列出了配置的线程数,其中有多少个线程是正在处理事务的,也就是活动的,还有多少等待处理的事务在队列里。

如果队列满了,超出了限制,新的事务就会开始被拒绝,你可以看到拒绝的事务的统计,这通常表示你的集群正处在一个资源瓶颈,因为一个满的队列表示你的集群或者节点正在以最大的速度处理事务,但是依然赶不上新事务增加的速度。

关于bulk的拒绝

如果你的线程队列出现拒绝请求的事情,那么醉有可能发生的就是bulk批量索引的请求,通过采用并发导入线程,很容易发给elasticsearch很多的bulk请求,并发请求越多越好吗?

现实中,任何集群都有一定的线程,造成入不敷出。一旦这个阈值达到了,你的队列就会被迅速的填满,新的bulk请求就会被拒绝。

这是一个好事,队列的拒绝是对压力的一个有效措施,他们告诉你你的集群正在处于最大的容量,这要好过把数据全部塞到内存队列里。增大队列大小不会提升性能,它只会隐藏问题,如果你的集群每秒只能处理1万个文档,这和你的队列大小是100还是一千万没有任何关系,你的集群每秒的处理能力仍然是1万个文档。

队列只会隐藏性能问题,并且带来数据丢失的风险,在队列里的表示还没有被处理的,如果你的节点挂了,那么这些请求就会永远的丢失了,此外队列会消耗很大的内存,这不是个好主意。

最好我们通过优雅的解决队列满了的问题来清理队列。当你遇到bulk拒绝请求时候,你应该采取如下措施:

1、停止插入线程3-5秒
2、从bluk请求里提取被拒绝的操作,可能大部分请求都成功了。bulk的响应里会告诉你哪些操作成功了,哪些操作被拒绝了。
3、把拒绝的操作重新生成一个新的bulk请求。
4、如果再有拒绝请求发生,就重复上面的步骤。

通过这种方式,你的代码会自然的适应你的集群的负载,自然的减压。

请求拒绝不是错误,它们只是表示你需要过会重试。

有十几个线程池,大部分你可以忽视,但是有少部分需要你特别注意:

indexing 正常的索引文档的请求
bulk 批量请求,这有区别于非批量的请求
get 根据id获取文档的操作
search 索引的检索和查询请求
merging 专门管理lucene合并的线程池

FS和Network部分(剩余空间和网络)

继续看node stats api返回的信息,你会看到一个关于文件系统的统计信息,剩余空间,数据存放目录,磁盘io等待。如果你没有监控剩余磁盘空间大小,你可以从这里得到。磁盘io也是很容易得到,但是一些更专业的命令行工具(例如iostat)可能更有用。

很显然,如果你的磁盘空间不足了,elasticsearch肯定完蛋了,所以一定要保证充足的磁盘空间。

下面是关于network统计的两个部分:

"transport": {
	"server_open": 13,
	"rx_count": 11696,
	"rx_size_in_bytes": 1525774,
	"tx_count": 10282,
	"tx_size_in_bytes": 1440101928
 },
 "http": {
	"current_open": 4,
	"total_opened": 23
 },

transport: 显示了网络传输的基本信息,这涉及到节点之间的通信(通常是9300端口)和一些客户端和节点之间的链接。如果你看到很多链接在这里,不要担心,elasticsearch会保持大量的节点之间的链接。

http表示关于http端口(通常是9200)的基本信息,如果你看到一个非常大的total_opened,并且在不断增加,这是一个很明确的信号:你的客户端没有使用HTTP的keep-alive。keep-alive的链接对性能很重要,因为不断的创建和断开socket链接是很昂贵的(同事也会浪费open files个数),确保你的客户端都使用了正确的配置。

Circuit Breaker(断路器)

最后我们来到最后一个部分,关于fieldata 阻断的统计(在《Circuit Breaker》章节中有介绍。

"fielddata_breaker": {
	"maximum_size_in_bytes": 623326003,
	"maximum_size": "594.4mb",
	"estimated_size_in_bytes": 0,
	"estimated_size": "0b",
	"overhead": 1.03,
	"tripped": 0
 }

这里,你可以看到最大阻断的大小(例如,你的查询请求使用多大的内存的时候,这个断路器就会进行左右)。这个部分就是告诉你断路器发挥作用的次数,以及当前配置的过载值,这个值是用来估计的(译者注:用来估计查询可能需要使用的内存)。因为有些查询比其它的比较难估计。

最主要的东西还是关于断路器起作用的次数的统计,如果这个值很大并且持续增加,表示你的查询需要优化,或者你需要更多的内存(整体上增加内存,或者增加更多的节点)。

原文地址:https://www.elastic.co/guide/en/elasticsearch/guide/current/_monitoring_individual_nodes.html

 ← 上一篇 下一篇 

[翻译]Elasticsearch重要文章之三:重要配置项的修改

Elasticsearch已经有很好的默认值,特别是涉及到性能相关的配置或者选项。如果你有什么拿不准的,最好就不要动它。我们已经目睹了数十个因为错误的设置而导致集群毁灭,因为它的管理者总认为他改动一个配置或者选项就可以带来100倍的提升。

注意:请阅读全文,所有的配置项都同等重要,和描述顺序无关,请阅读所有的配置选项,并应用到你的集群中。

其它数据库可能需要调优,但总得来说,Elasticsearch不需要。如果你遇到了性能问题,最好的解决方法通常是更好的数据布局或者更多的节点。在Elasticsearch中有很少的”神奇的配置项”,如果存在,我们也已经帮你优化了。

指定名字

Elasticsearch默认启动的集群名字叫elasticsearch,你最好给你的生产环境的集群改个名字,改名字的目的很简单,就是防止某个人的笔记本加入到了集群,造成意外。简单修改成elasticsearch_production ,会省掉多次心痛~。
你可以在你的elasticsearch.yml中修改:
cluster.name: elasticsearch_production

同样,修改节点的名字也是明智的,就像你现在可能发现的那样,Elasticsearch会在你的节点启动的时候随机给它指定一个名字。这在你开发的时候可能觉得很萌,但是当凌晨3点钟,你还在尝试会议哪台物理机是Tagak the Leopard Lord.的时候,你就不觉得萌了。

更重要的是,这些名师是在启动的时候产生的,每次启动节点,它都会得到一个新的名字,这可以使日志混淆,因为所有节点的名称都是不断变化的。
这些可能性都是很无聊的,我们建议你给每个及诶点一个有意义的名字-一个清楚的,描述性的名字,同样你可以在elasticsearch.yml中配置:
node.name: elasticsearch_005_data

路径

默认情况下,Eleasticsearch会把插件、日志以及你最重要的数据放在安装目录下。这会带来不幸的事故。即如果你重新安装Elasticsearch的时候就可能不小心把安装目录覆盖了,如果你不小心,你就可能把你的全部数据删掉了。

不要笑,这种情况,我们见过很多次了。

最好的选择就是把你的数据目录配置到安装目录以外的地方,同样你也可以选择转移你的插件和日志目录。

可以更改如下:
path.data: /path/to/data1,/path/to/data2

# Path to log files:
path.logs: /path/to/logs

# Path to where plugins are installed:
path.plugins: /path/to/plugins

注意:你可以通过逗号分隔指定多个目录。

数据可以保存到多个不同的目录,每个目录如果是挂载在不同的硬盘,做一个人RAID 0是一个简单而有效的方式。Elasticsearch会自动把数据分隔到不同的目录,以便提高性能。

最小主节点数

minimum_master_nodes的设定对你的集群的稳定及其重要,当你的集群中有两个masters的时候,这个配置有助于防止集群分裂。

如果你发生了一个集群分裂,你集群就会处在丢失数据的危险中,因为master节点是被认为是这个集群的最高统治者,它决定了什么时候新的索引可以创建,多少分片要移动等等。如果你有两个master节点,你的数据的完整性将得不到保证,因为你有两个master节点认为他们有集群的控制权。

这个配置就是告诉Elasticsearch当没有足够master候选节点的时候,就不要进行master选举,等master候选节点足够了才进行选举。

该配置必须应该配置成master候选节点的法定个数(大多数个),法定个数就是(master候选节点个数/2)+1. 这里有几个例子:
*如果你有10个节点(能保存数据,同时能成为master) 法定数就是6
*如果你有3个候选master,和100个数据节点,法定数就是2,你只要数数那些可以做master的节点数就可以了。
*如果你有两个节点,你遇到难题了,法定数当然是2,但是这意味着如果有一个节点挂掉,你整个集群就不可用了。设置成1可以保证集群的功能,但是就无法保证集群分裂了,像这样的情况,你最好至少保证有3个节点。

elasticsearch.yml中这样配置:
discovery.zen.minimum_master_nodes: 2

但是由于ELasticsearch是动态的,你可以很容易的添加和删除节点,这会改变这个法定个数,如果你不得不修改索引的节点的配置并且重启你的整个集群为了让配置生效,这将是非常痛苦的一件事情。
基于这个原因,minimum_master_nodes (还有一些其它配置),允许通过API调用的方式动态进行配置,当你的集群在线运行的时候,你可以这样修改配置:
PUT /_cluster/settings
{
“persistent” : {
“discovery.zen.minimum_master_nodes” : 2
}
}

这将成为一个永久的配置,并且无论你配置项里配置的如何,这个将优先生效。当你添加和删除master节点的时候,你需要更改这个配置。

集群恢复方面的配置项

当你集群重启时,几个配置项影响你的分片恢复的表现。首先,我们必须明白,如果什么也没配置将会发生什么。

想象一下假设你有10个节点,每个节点保存一个分片,主分片或者副分片,也就是有一个有5个主分片/1个副本 的索引。你需要停止整个集群进行休整(举个例子,为了安装一个新的驱动程序)。当你重启你的集群,很自然会出现5个节点已经起动了,还有5个还没启动的场景。

假设其它五个节点出问题,或者他们根本没有收到立即重启的命令。无论什么原因,你只要五个节点在线上。这五个节点会相互通信,选出一个master,从而形成一个集群,他们注意到数据不再均匀分布,因为有个节点在集群中丢失了,他们之间会立马启动分片复制。

最后,你的其它5个节点打开加入了集群,这些节点会发现他们的数据已经成为其它节点的副本了,所以他们删除本地数据(因为这份数据要么是多余的,要么是过时的)。然后整个集群重新进行平衡,因为集群的大小已经从5变成了10。

在整个过程中,你的节点会消耗磁盘和网盘,来回移动数据,因为没有更好的理由。对于有上T数据的大集群,这种数据的传输需要很长时间。如果等待所有的节点重启好了,整个集群再上线,所有的本地的数据都不需要移动。

现在我们知道问题的所在了,我们可以修改一个小配置就可以缓解这个事情,首先我们要给ELasticsearch一个严格的限制:
gateway.recover_after_nodes: 8

这将放置Elasticsearch进行数据恢复,在发现8个节点(数据节点或者master节点)之前。这个值的设定取决于个人喜好: 整个集群提供服务之前你希望有多少个节点在线?我们设置为8, 这意味着至少要有8个节点,该集群才可用。

现在我们要告诉Ealsticsearch集群中应该有多少个节点,并且我们希望集群需要多久等待所有节点:

gateway.expected_nodes: 10
gateway.recover_after_time: 5m

这意味着Elasticsearch会采取如下操作:
*至少等待8个节点上线
*等待5分钟,或者10个节点上线后,才进行数据恢复,这取决于哪个条件先达到。

这三个设置可以在集群重启的时候避免过多的分片交换。这可能会让数据恢复从数个小时缩短为几秒钟。
这些配置只能设置在config/elasticsearch.yml文件中,或者是在命令行里(这些配置是无法东塔修改的),它们只在整个集群重启的时候有实质性作用。

最好使用单播代替组播

Elasticsearch默认是被配置成使用多播发现节点。多播就是通过在你的网络中发送UDP的ping请求以发现节点,其它Elasticsearch会收到这些ping请求并且进行响应,这样随后就会形成一个集群。
多播对于开发环境是很好的,你不需要做什么事情,打开一些节点,他们自然的会发现对方形成一个集群。
正是因为这种易用性,你在生产环境中必须禁掉它。否在你得到的结果就是一个节点意外的加入到了你的生产环境,因为他们收到了一个错误的组播信号。对于组播本身并没有错。组播会导致一些愚蠢的问题,并且导致集群变的脆弱(例如:一个网络工程师正在捣鼓网络,而没有告诉你,你会发现所有的节点突然发现不了对方了)。

在生产环境中,建议使用单播代替组播,也就是说为Elasticsearch提供一些它应该去尝试连接的节点列表。一旦这个节点联系到组播列表中的一员,它就会得到整个集群所有节点的状态,然后它会联系master节点,并加入集群。

这意味着你的单播列表不需要包含你的集群中的所有节点,它只需要包含足够一个新节点联系上其中一个并且说上话就ok了。如果你使用master候选节点作为单播列表,你只要列出三个就可以了。这个配置在elasticsearch.yml文件中:
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: [“host1”, “host2:port”]

备注:请确认你已经关闭了组播(discovery.zen.ping.multicast.enabled: false),否则它会和单播同时存在。

Elasticsearch重要文章之四:监控每个节点(Indices部分)

集群的健康只是一个方面,它是对整个集群所有方面的一个很高的概括。节点状态的api是另外一个方面,它提供了关于你的集群中每个节点令你眼花缭乱的统计数据。

节点的状态提供了那么多的统计数据,在你很熟悉它们执勤,你可能不确定哪些指标是至关重要。我们会把需要监控的最重要的几个指标跳出来(我们建议你把所有的统计指标记录下来,例如使用Marvel插件,因为你不知道你哪天可能就需要)。

节点状态的API可以通过下面的方式执行
GET _nodes/stats

在输出内容的开头,我们可以看到集群的名字和我们第一个node的信息:

{
"cluster_name": "elasticsearch_zach",
"nodes": {
  "UNr6ZMf5Qk-YCPA_L18BOQ": {
	 "timestamp": 1408474151742,
	 "name": "Zach",
	 "transport_address": "inet[zacharys-air/192.168.1.131:9300]",
	 "host": "zacharys-air",
	 "ip": [
		"inet[zacharys-air/192.168.1.131:9300]",
		"NONE"
	 ],
   ...

节点会根据一个hash值的顺序来显示,也就是node的uuid值。还有一些关于node的网络属性会显示(例如传输地址和HOST)。这些信息有助于调试发现问题,比如那些节点没有加入集群。通常你可能会发现端口用错了,或者节点绑错了IP地址等等。

Indices部分

indices部分列出的是对于所有的索引在该节点上的汇总信息。

"indices": {
"docs": {
   "count": 6163666,
   "deleted": 0
},
"store": {
   "size_in_bytes": 2301398179,
   "throttle_time_in_millis": 122850
},

它返回的统计信息可以分成这样几个部分:
docs: 显示有多少文档在该节点,以及有多少删除的文档还没有从数据段中清除出去。
store: 显示该节点消耗了多少物理存储,这个数据包含主分片和副分片,如果throttle_time_in_millis太大,说明你设置的磁盘流量太低(参考段的合并一章节)

"indexing": {
   "index_total": 803441,
   "index_time_in_millis": 367654,
   "index_current": 99,
   "delete_total": 0,
   "delete_time_in_millis": 0,
   "delete_current": 0
},
"get": {
   "total": 6,
   "time_in_millis": 2,
   "exists_total": 5,
   "exists_time_in_millis": 2,
   "missing_total": 1,
   "missing_time_in_millis": 0,
   "current": 0
},
"search": {
   "open_contexts": 0,
   "query_total": 123,
   "query_time_in_millis": 531,
   "query_current": 0,
   "fetch_total": 3,
   "fetch_time_in_millis": 55,
   "fetch_current": 0
},
"merges": {
   "current": 0,
   "current_docs": 0,
   "current_size_in_bytes": 0,
   "total": 1128,
   "total_time_in_millis": 21338523,
   "total_docs": 7241313,
   "total_size_in_bytes": 5724869463
},

indexing: 表示索引文档的次数,这个是通过一个计数器累加计数的。当文档被删除时,它不会减少。注意这个值永远是递增的,发生在内部索引数据的时候,包括那些更新操作。

search:列出了主动检索的次数(open_contexts),查询总数,以及从节点启动到现在花在这些查询上的总时间。query_time_in_millis / query_total的比值可以作为你的查询效率的粗略指标。比值越大,每个查询用的时间越多,你就需要考虑调整或者优化。

后面关于fetch的统计,是描述了查询的第二个过程(也就是query_the_fetch里的fetch)。fetch花的时间比query的越多,表示你的磁盘很慢,或者你要fetch的的文档太多。或者你的查询参数分页条件太大,(例如size等于1万)

merges:包含lucene段合并的信息,它会告诉你有多少段合并正在进行,参与的文档数,这些正在合并的段的总大小,以及花在merge上的总时间。
如果你的集群写入比较多,这个merge的统计信息就很重要。merge操作会消耗大量的磁盘io和cpu资源。如果你的索引写入很多,你会看到大量的merge操作,一低昂要阅读《关于索引数据性能方面的提示》这一章节。

注意:更新和删除都会导致大量的合并,因为它们会产生段碎片,这些都需要进行合并。

"filter_cache": {
   "memory_size_in_bytes": 48,
   "evictions": 0
},
"id_cache": {
   "memory_size_in_bytes": 0
},
"fielddata": {
   "memory_size_in_bytes": 0,
   "evictions": 0
},
"segments": {
   "count": 319,
   "memory_in_bytes": 65812120
},
...

filter_cache:表示缓存的filter bitset所占的内存大小,以及一个filter缓存被淘汰的次数。大量的缓存淘汰预示着你可能需要增加你的filter缓存大小,或者你的filter不太适合缓存(例如,你的filter基数比较大,例如缓存当前时间的表达式。译注:意思就是你的filter基数很大,例如你的某个field是表示当前时间,你的filter肯定很大,缓存不容易利用上)

但是淘汰是个很难度量的评价,filter 是被缓存到每个段(segement)上的,在一个小段上淘汰比在一个大段上淘汰容易一些。如果你有很多淘汰,但是都是发生在小的段上,那对查询的性能影响也不大。

把这个淘汰的统计作为一个粗略的指导,如果你看到大量的淘汰,就要调查下你的filter,确保它们是比较适合缓存的。如果filters不断的淘汰,即便是在小的段上,对性能还是有影响的,所以你最好使用适合缓存的filter

id_cache:显示了父子mapping使用的内存,如果你使用了父子映射,id_cache就会在内存里位置一张链接表包含这种关系,这个统计告诉你多少内存正在使用。因为它和父子文档的个数有个明确的线性关系,所以对于这部分内存的使用,你可以做的事情很少,它是常驻内存的,所以你最好经常关注它。

field_data:显示了fielddata使用的内存,fielddata用于聚合、排序等。这里也有一个淘汰数,不像filter_cache,这里的淘汰数很有用,它必须是0或者接近0,因为fielddata 不是缓存,任何淘汰的代价都是很大的,必须要避免的。如果你看到了淘汰,你必须重新评估你的内存情况,关于fielddata的限制,以及查询,或者三者全部。

segments:告诉你当前节点的lucene 段的个数,这可能是一个很重要的数字。大多数的索引应该在50到150个段左右,即便是几T大小的数十亿的文档。大量的段会带来合并的问题(例如:合并赶不上段的产生)。注意这个统计是对一个节点上所有的索引而言的,记住哟。

其中内存的统计,可以告诉你Lucene的段自身需要多少内存。这里包括基础的数据结构,包括提交列表,词典,bloom过滤器等。段的数量多会增加承载这些数据结构的开销,这个内存的使用就是对这个开销的度量。

监控每个节点(ThreadPool部分)

ThreadPool部分

Elasticsearch 内部使用了线程池,通过这些线程池之间的合作完成工作,在需要时传递工作。一般来说你不需要调整和优化线程池。但是有时候你看着这些线程池的状态,对你掌握你的集群行为是很有帮助的。

这有十几个线程池,他们的格式都是类似的:

"index": {
     "threads": 1,
     "queue": 0,
     "active": 0,
     "rejected": 0,
     "largest": 1,
     "completed": 1
  }

每个线程都列出了配置的线程数,其中有多少个线程是正在处理事务的,也就是活动的,还有多少等待处理的事务在队列里。

如果队列满了,超出了限制,新的事务就会开始被拒绝,你可以看到拒绝的事务的统计,这通常表示你的集群正处在一个资源瓶颈,因为一个满的队列表示你的集群或者节点正在以最大的速度处理事务,但是依然赶不上新事务增加的速度。

关于bulk的拒绝

如果你的线程队列出现拒绝请求的事情,那么醉有可能发生的就是bulk批量索引的请求,通过采用并发导入线程,很容易发给elasticsearch很多的bulk请求,并发请求越多越好吗?

现实中,任何集群都有一定的线程,造成入不敷出。一旦这个阈值达到了,你的队列就会被迅速的填满,新的bulk请求就会被拒绝。

这是一个好事,队列的拒绝是对压力的一个有效措施,他们告诉你你的集群正在处于最大的容量,这要好过把数据全部塞到内存队列里。增大队列大小不会提升性能,它只会隐藏问题,如果你的集群每秒只能处理1万个文档,这和你的队列大小是100还是一千万没有任何关系,你的集群每秒的处理能力仍然是1万个文档。

队列只会隐藏性能问题,并且带来数据丢失的风险,在队列里的表示还没有被处理的,如果你的节点挂了,那么这些请求就会永远的丢失了,此外队列会消耗很大的内存,这不是个好主意。

最好我们通过优雅的解决队列满了的问题来清理队列。当你遇到bulk拒绝请求时候,你应该采取如下措施:

1、停止插入线程3-5秒
2、从bluk请求里提取被拒绝的操作,可能大部分请求都成功了。bulk的响应里会告诉你哪些操作成功了,哪些操作被拒绝了。
3、把拒绝的操作重新生成一个新的bulk请求。
4、如果再有拒绝请求发生,就重复上面的步骤。

通过这种方式,你的代码会自然的适应你的集群的负载,自然的减压。

请求拒绝不是错误,它们只是表示你需要过会重试。

有十几个线程池,大部分你可以忽视,但是有少部分需要你特别注意:

indexing 正常的索引文档的请求
bulk 批量请求,这有区别于非批量的请求
get 根据id获取文档的操作
search 索引的检索和查询请求
merging 专门管理lucene合并的线程池

FS和Network部分(剩余空间和网络)

继续看node stats api返回的信息,你会看到一个关于文件系统的统计信息,剩余空间,数据存放目录,磁盘io等待。如果你没有监控剩余磁盘空间大小,你可以从这里得到。磁盘io也是很容易得到,但是一些更专业的命令行工具(例如iostat)可能更有用。

很显然,如果你的磁盘空间不足了,elasticsearch肯定完蛋了,所以一定要保证充足的磁盘空间。

下面是关于network统计的两个部分:

"transport": {
	"server_open": 13,
	"rx_count": 11696,
	"rx_size_in_bytes": 1525774,
	"tx_count": 10282,
	"tx_size_in_bytes": 1440101928
 },
 "http": {
	"current_open": 4,
	"total_opened": 23
 },

transport: 显示了网络传输的基本信息,这涉及到节点之间的通信(通常是9300端口)和一些客户端和节点之间的链接。如果你看到很多链接在这里,不要担心,elasticsearch会保持大量的节点之间的链接。

http表示关于http端口(通常是9200)的基本信息,如果你看到一个非常大的total_opened,并且在不断增加,这是一个很明确的信号:你的客户端没有使用HTTP的keep-alive。keep-alive的链接对性能很重要,因为不断的创建和断开socket链接是很昂贵的(同事也会浪费open files个数),确保你的客户端都使用了正确的配置。

Circuit Breaker(断路器)

最后我们来到最后一个部分,关于fieldata 阻断的统计(在《Circuit Breaker》章节中有介绍。

"fielddata_breaker": {
	"maximum_size_in_bytes": 623326003,
	"maximum_size": "594.4mb",
	"estimated_size_in_bytes": 0,
	"estimated_size": "0b",
	"overhead": 1.03,
	"tripped": 0
 }

这里,你可以看到最大阻断的大小(例如,你的查询请求使用多大的内存的时候,这个断路器就会进行左右)。这个部分就是告诉你断路器发挥作用的次数,以及当前配置的过载值,这个值是用来估计的(译者注:用来估计查询可能需要使用的内存)。因为有些查询比其它的比较难估计。

最主要的东西还是关于断路器起作用的次数的统计,如果这个值很大并且持续增加,表示你的查询需要优化,或者你需要更多的内存(整体上增加内存,或者增加更多的节点)。

原文地址:https://www.elastic.co/guide/en/elasticsearch/guide/current/_monitoring_individual_nodes.html

 

 

posted @ 2019-08-23 17:59  Bigben  阅读(754)  评论(0编辑  收藏  举报