Elasticsearch使用问题—TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark

本文介绍了因测试服务器磁盘使用率过高导致Elasticsearch索引被标记为只读的问题及解决方案,包括调整ES配置、清理磁盘空间及服务器扩容等方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 问题描述

在公司产品开发迭代过程中,由于测试服务器磁盘使用率高达96%,代码部署到测试服务器进行测试时,发现创作模块不能新建创作、不能编辑创作,以及素材模块也不能添加新的素材以及修改之前的素材,只能读取之前的数据,一进行修改和新增的时候页面直接抛出一大串异常信息,查看服务端日志看到以下:

0.1 日志信息

org.elasticsearch.cluster.block.ClusterBlockException: index [.ds-ilm-history-5-2022.05.28-000003] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];index [.ds-ilm-history-5-2022.06.27-000004] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];index [.ds-ilm-history-5-2022.04.28-000002] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];

从日志信息上可以得到一些信息:一个是请求太多,另一个是磁盘超过阈值;这两个原因都有可能触发ES主动给索引上锁。

1. 请求过多引起上锁解决方案

由于前段时间有在测试环境对创作写入接口进行压测,所以当时我初步判断是因为压测的时候请求次数过多引起 ES 节点服务器内存超过限制,ES 主动给索引上锁,然后再 Kibana 开发工具上执行以下命令:

PUT _all/_settings
{
  "index.blocks.read_only_allow_delete": null
}

执行命令后,ES可以执行几次的写入操作了,但还是会触发上锁,显然这个并不是这次问题根本原因,但出于也有可能引发同样的问题,所以也记录以下这个解决方法

2. 磁盘使用超过阈值解决方案

在执行完方案一之后仍然没有解决问题,于是判断是磁盘超过阈值而导致问题的发生

2.1 ES 警告日志

在查询 ES 节点日志信息当中,发现 ES 一直在打印一个警告信息

[WARN ][o.e.c.r.a.DiskThresholdMonitor] [node01] flood stage disk watermark [95%] exceeded on [NOe0S30GTKm4BSFxz6ndUw][node01][/data/es/node01/nodes/0] free: 3.7gb[3.8%], all indices on this node will be marked read-only

在这里插入图片描述

2.2 查询ES节点磁盘使用情况

df -h

执行完命令后发现,Linux 服务器磁盘使用率已经高达 96% 了,由于我们在部署 ES 的时候并没有针对磁盘使用率进行任何配置,ES 磁盘使用率配置默认上限为 95%,这一参数可以参考 ES 源码:

public static final Setting<RelativeByteSizeValue> CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_SETTING =
        new Setting<>("cluster.routing.allocation.disk.watermark.flood_stage.frozen", "95%",
            (s) -> RelativeByteSizeValue.parseRelativeByteSizeValue(s,  "cluster.routing.allocation.disk.watermark.flood_stage.frozen"),
            Setting.Property.Dynamic, Setting.Property.NodeScope);

源码地址:https://github.com/elastic/elasticsearch/blob/v7.14.2/server/src/main/java/org/elasticsearch/cluster/routing/allocation/DiskThresholdSettings.java

警告代码:

for (final ObjectObjectCursor<String, DiskUsage> entry : usages) {
            final String node = entry.key;
            final DiskUsage usage = entry.value;
            final RoutingNode routingNode = routingNodes.node(node);

            if (isDedicatedFrozenNode(routingNode)) {
                ByteSizeValue total = ByteSizeValue.ofBytes(usage.getTotalBytes());
                long frozenFloodStageThreshold = diskThresholdSettings.getFreeBytesThresholdFrozenFloodStage(total).getBytes();
                if (usage.getFreeBytes() < frozenFloodStageThreshold) {
                    logger.warn("flood stage disk watermark [{}] exceeded on {}",
                        diskThresholdSettings.describeFrozenFloodStageThreshold(total), usage);
                }
                // skip checking high/low watermarks for frozen nodes, since frozen shards have only insignificant local storage footprint
                // and this allows us to use more of the local storage for cache.
                continue;
            }

            if (usage.getFreeBytes() < diskThresholdSettings.getFreeBytesThresholdFloodStage().getBytes() ||
                usage.getFreeDiskAsPercentage() < diskThresholdSettings.getFreeDiskThresholdFloodStage()) {

                nodesOverLowThreshold.add(node);
                nodesOverHighThreshold.add(node);
                nodesOverHighThresholdAndRelocating.remove(node);

                if (routingNode != null) { // might be temporarily null if the ClusterInfoService and the ClusterService are out of step
                    for (ShardRouting routing : routingNode) {
                        String indexName = routing.index().getName();
                        indicesToMarkReadOnly.add(indexName);
                        indicesNotToAutoRelease.add(indexName);
                    }
                }

                logger.warn("flood stage disk watermark [{}] exceeded on {}, all indices on this node will be marked read-only",
                    diskThresholdSettings.describeFloodStageThreshold(), usage);

          

源码地址:https://github.com/elastic/elasticsearch/blob/v7.14.2/server/src/main/java/org/elasticsearch/cluster/routing/allocation/DiskThresholdMonitor.java

所以,我们到这可以确定问题所在了

2.3 解决方案

针对这个问题,我们可以采用以下几个解决方案:

  1. 按照官方文档进行配置(文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/6.2/disk-allocator.html)
  2. 清理服务器磁盘
  3. 对服务器进行扩容

由于使用率已经高达 96% 了,所以感觉更改配置也撑不了多久,所以直接从第二个方案开始执行了,在清理了一些东西之后,磁盘使用率已经回到了 55%,应该能撑上一段时间了,如果不确定哪些磁盘文件能清理或者说清理磁盘依旧没有太大成效,下下策就只能去花钱扩容了

参考文档:

ElasticSearch-磁盘空间不够引起的问题:https://www.jianshu.com/p/55fd8a0b120b

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/6.2/disk-allocator.html

<think>好的,我现在需要帮助用户解决Elasticsearch 7.16.2中配置JAVA_HOME路径的问题,用户提供的JDK路径是/opt/ddm7/elasticsearch-7.16.2/JDK/bin/java。首先,我需要回想一下Elasticsearch的Java环境配置方法。通常,Elasticsearch会依赖JAVA_HOME环境变量来定位Java的安装位置。但有时候,用户可能需要在Elasticsearch的配置文件中直接指定Java路径,尤其是在系统中有多个Java版本或者默认的JAVA_HOME没有正确设置的情况下。 用户提到的是Elasticsearch 7.16.2,这个版本可能需要Java 11或更高版本。首先,我需要确认用户提供的JDK路径是否正确。路径是/opt/ddm7/elasticsearch-7.16.2/JDK/bin/java,看起来用户可能将JDK放在了Elasticsearch的安装目录下,这是一个常见做法,尤其是当用户希望每个Elasticsearch实例使用特定的JDK版本时。 接下来,配置JAVA_HOME的方法可能有几种。一种是在启动Elasticsearch之前设置环境变量,另一种是在Elasticsearch的启动脚本中直接指定Java路径。对于Elasticsearch来说,可能需要在bin目录下的elasticsearch脚本中设置ES_JAVA_HOME。因为根据Elasticsearch的文档,ES_JAVA_HOME变量会覆盖系统级的JAVA_HOME设置,这对于多Java环境特别有用。 用户可能已经尝试过设置系统级的JAVA_HOME,但发现Elasticsearch没有正确识别,所以需要直接配置Elasticsearch使用的Java路径。因此,正确的做法是设置ES_JAVA_HOME为JDK的安装目录,而不是到bin/java的可执行文件。用户提供的路径是到bin/java,而ES_JAVA_HOME应该指向JDK的根目录,即/opt/ddm7/elasticsearch-7.16.2/JDK,而不是包含bin的路径。 所以,用户需要编辑Elasticsearch的启动脚本或者在配置文件中设置ES_JAVA_HOME。可能的步骤包括: 1. 检查elasticsearch-env脚本,确认是否已经正确读取ES_JAVA_HOME。 2. 在/etc/elasticsearch/jvm.options或者elasticsearch的配置文件中设置ES_JAVA_HOME。 3. 或者直接在启动时通过命令行参数指定ES_JAVA_HOME。 另外,用户的环境可能涉及到不同的shell配置,比如bash或者zsh。根据引用[3]和[4],用户可能在使用zsh,所以需要确保在.zshrc中正确设置环境变量,并通过source命令使其生效。但如果是通过Docker安装(如引用[2]),可能需要不同的配置方法,比如在Dockerfile或启动容器时设置环境变量。 用户可能遇到的错误是Elasticsearch启动时找不到合适的Java版本,或者在日志中报告JAVA_HOME未正确配置。需要指导用户通过设置ES_JAVA_HOME到正确的JDK目录来解决此问题,并验证Java版本是否符合要求。 最后,需要验证配置是否生效,可以通过启动Elasticsearch并检查日志,或者运行./bin/elasticsearch -V来查看使用的Java版本信息。</think>### 解决Elasticsearch 7.16.2的JAVA_HOME配置问题 #### 步骤说明 1. **确认JDK路径有效性** 确保路径 `/opt/ddm7/elasticsearch-7.16.2/JDK` 是JDK的根目录(包含 `bin`、`lib` 等子目录)。若路径指向的是 `bin/java` 文件,需改为父目录: $$ \text{正确路径:}/opt/ddm7/elasticsearch-7.16.2/JDK $$ 2. **设置环境变量 `ES_JAVA_HOME`** Elasticsearch优先使用 `ES_JAVA_HOME` 而非系统级 `JAVA_HOME`。根据你的Shell类型(如zsh)编辑配置文件: ```bash # 如果是zsh(macOS默认) echo 'export ES_JAVA_HOME="/opt/ddm7/elasticsearch-7.16.2/JDK"' >> ~/.zshrc source ~/.zshrc # 使配置生效[^3][^4] ``` 3. **验证环境变量** 执行以下命令确认路径是否生效: ```bash echo $ES_JAVA_HOME # 应输出/opt/ddm7/elasticsearch-7.16.2/JDK ``` 4. **修改Elasticsearch启动脚本(可选)** 如果环境变量未生效,直接编辑Elasticsearch启动脚本 `bin/elasticsearch`,在文件开头添加: ```bash export ES_JAVA_HOME="/opt/ddm7/elasticsearch-7.16.2/JDK" ``` 5. **检查Java版本兼容性** Elasticsearch 7.16.2要求Java 11[^2],运行以下命令验证: ```bash $ES_JAVA_HOME/bin/java -version ``` 输出应包含 `11.x.x`。 6. **启动Elasticsearch并验证** 通过以下命令启动服务并检查日志: ```bash # 后台启动并指定PID文件(参考引用[1]) ./bin/elasticsearch -p /tmp/elasticsearch-pid -d tail -f logs/elasticsearch.log # 查看日志中是否有Java环境相关错误 ``` #### 注意事项 -使用Docker部署,需在容器启动时指定环境变量[^2]: ```bash docker run -e "ES_JAVA_HOME=/opt/ddm7/elasticsearch-7.16.2/JDK" elasticsearch:7.16.3 ``` - 确保JDK目录权限允许Elasticsearch进程访问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值