史前史
我在 CentOS 6.5 上运行 elasticsearch 和 SugarCRM7。每天我都会遇到同样的问题:java outOfMemory 错误。发生这种情况是因为 vm.max_map_count 值太小,只有当建议值为 262144 时才为 65530。
问题
问题是 vm.max_map_count 似乎无法改变:
在 root 下更改
sudo sysctl -w vm.max_map_count=262144
返回
错误:密钥‘vm.max_map_count’上的权限被拒绝
尽管
ps aux | grep java
仅返回 grep 进程
elasticsearch 启动时更改
sudo service elasticsearch start
也返回错误
错误:密钥‘vm.max_map_count’上的权限被拒绝
启动 elasticsearch:[确定]
通过文件手动更改(肮脏的黑客):
sudo vi /proc/sys/vm/max_map_count
也不起作用:
“/proc/sys/vm/max_map_count” [只读] 1L,6C
-- 插入 -- W10:警告:更改只读文件
E45:设置了“readonly”选项(添加!以覆盖)
“/proc/sys/vm/max_map_count”E212:无法打开文件进行写入
尽管
ls -la /proc/sys/vm/ | grep max_map_count
返回
-rw-r--r-- 1 root root 0 4月 10 09:36 max_map_count
(但我猜这对于 Linux 谈论 /proc 目录来说是正常的)
那么我该如何更改此变量的值?每晚重新启动 elasticsearch 不是一个好主意...或者至少有人知道为什么会发生此错误?
答案1
您快完成了,无论是虚拟机还是物理机,这些设置总是可以更改的。
我将展示 3 种方法。
一些预先信息:
1)如果可能的话最好以root身份执行。
2)/进程在 unix 上,它不是一个真正的文件系统,而是一个内存内核文件系统,但它看起来像一个普通的磁盘文件系统。您可以称其为“假文件系统”或“特殊文件系统”,您无法使用 vi 或任何其他编辑器编辑这些假文件,因为它们不是文件,它们只是看起来像文件。几年前我也遇到过同样的问题。
但改变它们的值很简单,只需要另一种“机制”来编辑它们。
我会解释一下:首先,需要是 root:(sudo 在某些发行版中有效,但在您尝试过的其他一些发行版中无效,第一种方法是通用的,适用于任何 Linux、macOS 或任何基于 Unix 的发行版。希望您可以访问 root 密码。
按照提示继续:
$ su root
输入 root 密码。
现在您是 root 了,让我们检查一下当前的值:/proc/sys/vm/max_map_count
$ cat /proc/sys/vm/max_map_count
65536
让我们改变它:
echo 262144 > /proc/sys/vm/max_map_count
我们来验证一下:
cat /proc/sys/vm/max_map_count
262144
完成了!并且已经应用并正常运行。通过更改 /proc 下任何伪文件的值,设置会立即生效。但它们在重启后不会保留。您可以尝试使用值并测量性能变化elasticsearch 工具或任何其他应用程序或系统指标。调整您的系统,将值写在纸上,保留最佳值。如果出现任何错误,重新启动,它们将全部恢复为原始值,然后重新开始,直到所有期望值都达到最佳值。/proc 下有很多磁盘和内存可调参数。如果您调整得当(并有时间),它们会带来巨大的差异和性能提升。您走在正确的道路上。
如果满意,我们就让它们永久存在:
第一种方法:
使用/etc/rc.local
vi /etc/rc.local
将所有参数放入 rc.local 文件中,例如:
echo 220000000 > /proc/sys/vm/dirty_background_bytes
echo 320000000 > /proc/sys/vm/dirty_bytes
echo 0 > /proc/sys/vm/dirty_background_ratio
echo 0 > /proc/sys/vm/dirty_ratio
echo 500 > /proc/sys/vm/dirty_writeback_centisecs
echo 4500 > /proc/sys/vm/dirty_expire_centisecs
echo 1 > /proc/sys/net/ipv4/tcp_rfc1337
echo 10 > /proc/sys/vm/swappiness
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo 120 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 0 > /proc/sys/vm/zone_reclaim_mode
echo deadline > /sys/block/sda/queue/scheduler
echo 8 > /sys/class/block/sda/queue/read_ahead_kb
echo 1048575 > /proc/sys/vm/max_map_count
退出 vi 编辑器并保存文件。
这些参数将在每次重启时、所有 init 服务启动之后、登录提示显示之前设置。
(/etc/rc.local文件在所有启动 Linux 服务之后执行,如果 elasticsearch 在它之前作为服务启动,它可能不起作用,但是如果您将来需要,这种方法在另一个设置上会很有用,或者您可以通过将它们放在 elasticsearch 初始化脚本中来使用,因为初始化脚本以 root 身份运行,所以在初始化脚本中使用上面的语法相同)
您也可以立即复制并粘贴它们以进行即时更改。上述参数在我的 apache cassandra 服务器上有效、经过调整并正在运行。如果您愿意,请尝试将它们作为调整您的服务器的起点。
使它们永久化的第二种方法:
现在参数将在 Linux 上的任何启动服务之前设置。
编辑/etc/sysctl.conf,将参数放入其中
vm.max_map_count=1048575
vm.zone_reclaim_mode=0
vm.dirty_background_bytes=220000000
vm.dirty_background_ratio=0
vm.dirty_bytes=320000000
vm.dirty_ratio=0
vm.swappiness=10
继续和其他人一起,保存/etc/sysctl.conf,重新启动服务器以应用更改,或者执行:系统控制-p无需重启即可应用更改。重启后更改仍将有效。
上面两种方法是最常见的。还有一种方法,可能对你有用,那就是使用须藤,就像你正在做的一样:
代替:
sudo sysctl -w vm.max_map_count=262144
尝试:
echo 262144 | sudo tee /proc/sys/vm/max_map_count
它在 ubuntu 上运行。
核实:
user@naos:~$ cat /proc/sys/vm/max_map_count
262144
希望我能提供一些帮助,至少提供 3 种不同的选项来解决这个问题,因为你的问题已经提出近一年了 ;)
问候,拉斐尔·普拉多
答案2
我认为您的“虚拟机”实际上是一个 OpenVZ 容器(您可以通过运行来验证这一点virt-what
)。
在这种情况下,您无法更改vm.max_map_count
sysctl 或许多其他值。这些值是固定的。
这是 elasticsearch 的一个众所周知的问题(问题 #4978)。不仅仅是 Elasticsearch。众所周知,Java 应用程序在各种 OpenVZ 提供商上的表现都不佳,主要是因为主机通常调整不佳,你对此无能为力。该问题上的一位评论者完全赞同我的建议:
joshuajonah 于 2015 年 10 月 20 日发表评论
这太疯狂了。我想我要换一台 KVM VPS 了。
答案3
您可以按照官方说明进行操作:
sysctl -w vm.max_map_count=262144
要使更改永久更新 /etc/sysctl.conf 中的 vm.max_map_count 设置
看https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html