You need to enable JavaScript to run this app. Scrapy多进程写Elasticsearch遇TOO_MANY_REQUESTS只读块异常排查咨询
优惠活动
大模型
产品
解决方案
定价
更多

Scrapy多进程写Elasticsearch遇TOO_MANY_REQUESTS只读块异常排查咨询

问题根因

你遇到的429报错不是写入并发太高触发的ES限流,报错里的cluster_block_exception是ES的磁盘保护机制触发的:ES检测到节点磁盘剩余空间低于默认阈值后,自动把所有索引标记为只读(仅允许删除,禁止写入),所有写入请求都会被拦截。

为什么df看磁盘没超却触发告警

  • 你的ES跑在Docker容器里(日志里的elasticsearch_1是Docker容器名),ES读取的是自身数据目录所在文件系统的可用空间,不是你在macOS下df看到的全分区通用值
  • ES默认磁盘洪泛水位阈值是:磁盘使用率超95%,或剩余可用空间小于5GB。告警里显示ES节点实际可用空间只有3.8GB,低于5GB阈值,所以触发了只读保护。
  • 你执行的df输出里/dev/disk1s1(macOS系统数据分区)使用率已经到98%,剩余可用实际只有约5.7GB,扣掉Docker镜像、系统缓存占用的部分后,ES能用到的可用空间进一步降到3.8GB,符合告警触发条件。
解决步骤

1. 先临时解除索引只读状态

执行以下ES API命令,把所有被标记为只读的索引的限制去掉:

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

注意:这只是临时操作,磁盘空间问题没解决的话,ES每30秒做一次磁盘检测,过不了多久会再次自动把索引设为只读。

2. 先解决磁盘空间不足的核心问题

优先清磁盘,不然调再多阈值都是临时方案:

  • 清理Docker无用资源:执行docker system prune -a删掉没用的镜像、停止的容器、悬空缓存,释放宿主机磁盘空间
  • 清理ES冗余数据:删掉不需要的旧索引、过期的测试文档,直接释放ES数据目录的占用
  • 给ES单独挂大容量数据盘:别让ES和系统盘、Docker系统镜像共用分区,避免其他程序占了空间挤占ES的可用额度

3. 小容量测试环境可调整磁盘水位阈值

如果是测试环境,ES部署的磁盘本身空间就不大(比如总共只有10GB左右),可以手动调低洪泛水位的剩余空间阈值,比如改成剩余2GB以下才触发告警:

临时调整(重启ES后失效)

直接执行集群配置修改API:

PUT _cluster/settings
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.flood_stage": "2gb",
    "cluster.routing.allocation.disk.watermark.high": "85%",
    "cluster.routing.allocation.disk.watermark.low": "80%"
  }
}

永久调整

修改ES配置文件elasticsearch.yml,加以下内容,重启ES生效:

cluster.routing.allocation.disk.watermark.low: 80%
cluster.routing.allocation.disk.watermark.high: 85%
cluster.routing.allocation.disk.watermark.flood_stage: 2gb

别把阈值设得太低,不然磁盘真写满会导致ES节点崩溃、数据损坏。

4. 优化并发写入配置,支撑多进程爬虫的写入需求

等磁盘问题解决、索引只读限制解除后,再调配置提高写入承载力,避免后续真的触发并发限流:

ES端调整

  • 适当增大写入队列容量:修改elasticsearch.yml
    thread_pool.write.queue_size: 1000
    
  • 强制用批量写入:别每爬一条就调一次ES的单条index接口,攒够100~500条文档再走_bulk接口批量提交,能减少90%以上的请求次数
  • 调低索引刷新频率:把索引的refresh_interval从默认的1s改成5s,减少索引刷新的IO开销
    PUT /你的索引名/_settings
    {
      "index": {
        "refresh_interval": "5s"
      }
    }
    

爬虫端调整

  • 控制写入并发:别让所有爬虫进程同时往ES发请求,加个中间缓冲队列(比如用Redis),所有爬虫进程把要写的文档先扔到队列里,再用少量独立进程批量消费队列写ES,避免瞬间并发打满ES的写入线程池
  • 开启客户端重试:ES客户端遇到429报错时做指数退避重试,别直接报错终止爬虫任务

内容的提问来源于stack exchange,提问作者omars

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.11 01:54:04