“训练有素的人也正在踩耙。
但另一方面,笔在哪里。”Elasticsearch是一个很棒的工具,但是每个工具不仅需要
调整和
维护 ,还需要注意细节。 有些微不足道,躺在地上,而另一些则隐藏得如此之深,以至于需要超过一天的时间进行搜索,而不是十几杯咖啡和一公里的神经。 在本文中,我将向您介绍我踩踏的弹性设置中的九种出色的耙子。
我将按照证据的降序排列耙。 从在生产状态下建立并进入集群的阶段可以预见和规避的那些,到带来最多体验(和眼睛中的星星)的非常奇怪的那些。
数据节点必须相同
“集群正在以最慢的数据节点的速度运行”-一个痛苦的公理。 但是还有一个与性能无关的明显点:弹性器不考虑磁盘空间,而是考虑分片,并尝试在数据节点之间平均分配它们。 如果某些数据节点比其他数据节点有更多的空间,那么闲置将毫无用处。
弃用日志
可能发生的情况是,有人没有使用最现代的方式将数据发送到弹性模块,从而无法在执行查询时设置Content-Type。 在此列表中,例如heka,或日志通过内置方式离开设备时)。 在这种情况下,不建议使用。 日志开始以惊人的速度增长,并且对于每个请求,其中都会显示以下几行:
[2018-07-07T14:10:26,659][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,670][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,671][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,673][WARN ][oedrRestController] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header. [2018-07-07T14:10:26,677][WARN ][oedrRestController ] Content type detection for rest requests is deprecated. Specify the content type using the [Content-Type] header.
平均而言,每5到10毫秒发送一次请求-每次将新行添加到日志中。 这会对磁盘子系统的性能产生负面影响,并增加iowait。 可以关闭Deprecation.log,但这不是太合理。 为了将弹性日志收集到其中,而不收集垃圾,我仅禁用了oedrRestController类的日志。
为此,将以下构造添加到logs4j2.properties:
logger.restcontroller.name = org.elasticsearch.deprecation.rest.RestController logger.restcontroller.level = error
它将把此类的日志提高到错误级别,并且它们将不再属于deprecation.log。
.kibana
典型的群集安装过程是什么样的? 我们放置节点,将它们组合成一个集群,放置x-pack(需要它的人),当然还有Kibana。 我们开始,确认一切正常,并且Kibana看到了集群,然后继续进行配置。 问题在于,在新安装的群集上,默认模板如下所示:
{ "default": { "order": 0, "template": "*", "settings": { "number_of_shards": "1", "number_of_replicas": "0" } }, "mappings": {}, "aliases": {} }
存储所有设置的.kibana索引在一个副本中创建。
曾经有一种情况,由于硬件故障,群集中的一个数据节点被杀死。 它很快进入一致状态,从相邻的数据节点中产生了该碎片的副本,但是幸运的是,唯一具有.kibana索引的碎片位于此数据节点上。 情况陷入僵局-集群处于活动状态,处于工作状态,Kibana处于红色状态,而我的电话因迫切需要其日志的员工的电话而被撕毁。
所有这些都可以简单地解决。 到目前为止,什么都没有下降:
XPUT .kibana/_settings { "index": { "number_of_replicas": "<__>" } }
XMX / XMS
该
文档说“不超过32 GB”,这是正确的。 但这是正确的,您不需要在服务设置中进行安装
-Xms32g -Xmx32g
因为它已经超过32 GB,所以在这里我们遇到了一个有趣的Java处理内存细微差别。 超过一定限制后,Java将停止使用压缩指针,并开始不合理地消耗大量内存。 检查压缩的指针是否使用运行Elasticsearch的Java机器非常简单。 我们在服务日志中查看:
[2018-07-29T15:04:22,041][INFO][oeeNodeEnvironment][log-elastic-hot3] heap size [31.6gb], compressed ordinary object pointers [true]
不应超过的内存量尤其取决于所使用的Java版本。 要计算您所需要的确切体积,请参阅
文档 。
现在我已经在弹性的所有数据节点上安装了:
-Xms32766m -Xmx32766m
这似乎是一个平庸的事实,并且文档描述得很好,但是我经常遇到我错过了这一点的Elasticsearch安装,并且Xms / Xmx设置为32g。
/ var / lib / elasticsearch
这是在Elasticsearch中存储数据的默认路径。 yml:
path.data: /var/lib/elasticsearch
我通常在那里安装一个大型RAID阵列,这就是为什么:我们为ES指定几种存储数据的方式,例如:
path.data: /var/lib/elasticsearch/data1, /var/lib/elasticsearch/data2
在data1和data2中安装了不同的磁盘或RAID阵列。 但是弹性不会平衡,并且不会在这些路径之间分配负载。 首先,他填写了一个部分,然后开始写另一个部分,因此存储上的负载将不均衡。 知道了这一点,我做出了明确的决定-将RAID0 / 1中的所有磁盘组合在一起,并将其安装在path.data中指定的路径中。
available_processors
不,我不是说现在摄取节点上的处理器。 如果查看正在运行的节点的属性(通过_nodes API),则会看到类似以下内容:
"os". { "refresh_interval_in_millis": 1000, "name": "Linux", "arch": "amd64", "version": "4.4.0-87-generic", "available_processors": 28, "allocated_processors": 28 }
可以看出,该节点在具有28个核心的主机上运行,并且Elastic正确地确定了它们的数量并在所有核心上启动。 但是,如果有32个以上的内核,则有时会发生以下情况:
"os": { "refresh_interval_in_millis": 1000, "name": "Linux", "arch": "amd64", "version": "4.4.0-116-generic", "available_processors": 72, "allocated_processors": 32 }
您必须强制该服务可用的处理器数量-这对节点的性能有很好的影响。
processors: 72
thread_pool.bulk.queue_size
在上
一篇文章的thread_pool.bulk.rejected部分中
,有一个指标-请求添加数据失败的次数。
我写道,该指标的增长是一个非常糟糕的信号,开发人员建议不要设置线程池,而是向群集中添加新节点-可以解决性能问题。 但是需要规则以便有时打破规则。 而且,并非总是可以“用铁抛出问题”,因此,应对批量请求失败的措施之一就是增加此队列的大小。
默认情况下,队列设置如下所示:
"thread_pool": { "bulk": { "type": "fixed", "min": 28, "max": 28, "queue_size": 200 } }
算法如下:
- 我们收集白天平均队列大小的统计信息(即时值存储在thread_pool.bulk.queue中);
- 小心地将queue_size的大小增加到略大于活动队列的平均大小的大小-因为超过该大小时会发生故障;
- 我们增加了池的大小-这不是必需的,但可以接受。
为此,请将以下内容添加到主机设置中(当然,您将拥有自己的值):
thread_pool.bulk.size: 32 thread_pool.bulk.queue_size: 500
并且在重启节点之后,我们一定会监视负载,I / O,内存消耗。 并在必要时回滚所有设置。
重要提示:这些设置仅对正在接收新数据的节点有意义。初步索引创建
正如我在本系列的第一
篇文章中所说的,我们使用Elasticsearch存储所有微服务的日志。 底线很简单-一个索引可以一天存储一个组件的日志。
随之而来的是,每天都会根据微服务的数量创建新索引-因此,每天晚上早些时候,弹性体陷入崩溃大约8分钟,而同时又创建了一百个新索引,数百个新分片,磁盘加载计划不可用,队列增加了将日志发送到主机上的弹性设备,Zabbix像圣诞树一样发出警报。
为避免这种情况,编写Python脚本来预先创建索引是常识。 脚本的工作方式是这样的:它查找今天的索引,提取它们的映射,并使用相同的映射创建新索引,但是要保留前一天的索引。 它在cron上运行,在Elastic负载最少的那几个小时内运行。 该脚本使用elasticsearch库,可在
GitHub上使用 。
透明的父级大页面
一旦发现运行数据接收的弹性节点在高峰时段开始在负载下挂起。 而且有一个非常奇怪的症状:所有处理器内核的使用率都降为零,但是该服务挂在内存中,正确侦听端口,不执行任何操作,不响应请求,并在一段时间后退出集群。 该服务不响应systemctl重新启动。 只有好的旧杀-9有所帮助。
直到坠落的那一刻,服务日志中的常规图片-才是空的,这在标准的监视工具上并没有发现。 此时,java机器的内存转储也是不可能的。
但是,正如他们所说,“我们是专业人士,所以一段时间后,我们用谷歌搜索了解决方案。” 一个类似的问题覆盖在
describe.elastic.co上的线程中,结果证明是与透明大页面有关的内核错误。 一切都通过使用sysfsutils软件包关闭内核中的thp来解决。
检查是否启用了透明的大页面很简单:
cat /sys/kernel/mm/transparent_hugepage/enabled always madvise [never]
如果[总是]在那里,则有潜在的危险。
结论
这是主要的因素(实际上,当然还有更多),作为Elasticsearch集群的管理员,我碰巧踩了一年半。 我希望这些信息能在通往理想的Elasticsearch集群的艰难而神秘的旅程中派上用场。
感谢插图Anton Gudim-他的
instagram上还有很多好处。