You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose多实例连PostgreSQL遇DNS解析临时失败求助

问题:Docker Compose环境中PostgreSQL服务DNS解析偶发失败及相关问题

环境信息

  • Docker Compose运行app服务40个实例(--scale app=40),宿主机配置56核CPU、256GB内存
  • 所有app实例连接同一编排内的db服务(PostgreSQL单实例,启动前已确认就绪可接受连接)
  • 版本信息:
    • Docker 20.10.18
    • Docker Compose v2.5.0
    • Python 3.9.7
    • psycopg2 2.9.3
  • 磁盘情况:根目录/dev/mapper/vps-vg-root总容量665G,已用355G,剩余277G(使用率57%)

偶发错误现象

DNS解析失败错误

app实例偶尔抛出psycopg2连接错误:

psycopg2.OperationalError:
  could not translate host name "db" to address:
    Temporary failure in name resolution

完整堆栈跟踪:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 3361, in _wrap_pool_connect
    return fn()
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 310, in connect
    return _ConnectionFairy._checkout(self)
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 868, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 476, in checkout
    rec = pool._do_get()
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 146, in _do_get
    self._dec_overflow()
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 208, in raise_
    raise exception
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 143, in _do_get
    return self._create_connection()
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 256, in _create_connection
    return _ConnectionRecord(self)
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 371, in __init__
    self.__connect()
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 666, in __connect
    pool.logger.debug("Error on connect(): %s", e)
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 208, in raise_
    raise exception
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 661, in __connect
    self.dbapi_connection = connection = pool._invoke_creator(self)
  File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 241, in <lambda>
    return lambda crec: creator()
  File "/app/scripts/database_connectors.py", line 112, in connector
    res = psycopg2.connect(**DB_PARAMETERS)
  File "/usr/local/lib/python3.9/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "db" to address: Temporary failure in name resolution

出现该错误的容器内执行psql命令同样报错:

psql -d postgres://postgres@db:5432/mydatabase
psql: error: could not translate host name "db" to address: Temporary failure in name resolution

关联的共享内存错误(不同时出现)

偶尔出现PostgreSQL共享内存调整失败错误:

psycopg2.errors.DiskFull:
  could not resize shared memory segment "/PostgreSQL.3516559362" to 146703328 bytes:
    No space left on device

或SQLAlchemy包装后的错误:

sqlalchemy.exc.OperationalError:
  (psycopg2.errors.DiskFull) could not resize shared memory segment "/PostgreSQL.3516559362" to 146703328 bytes:
    No space left on device

错误原因分析

DNS解析失败的核心原因

  1. Docker内置DNS服务并发过载:40个app实例同时发起DNS查询,Docker默认的docker-dns服务在高并发下出现短暂响应超时,导致部分实例解析db失败。
  2. 容器DNS缓存缺失/配置不合理:容器默认DNS缓存时长短、重试次数少,频繁重复查询进一步加剧DNS服务器压力。
  3. 宿主机网络栈资源紧张:大量容器运行导致UDP端口耗尽或DNS请求包丢失,引发解析失败。

共享内存错误的关联逻辑

虽然磁盘剩余空间充足,但PostgreSQL共享内存段存储在/dev/shm(内存文件系统)中。当宿主机内存被40个app实例+PostgreSQL大量占用时,/dev/shm空间不足,导致PostgreSQL无法调整共享内存大小,触发类似磁盘满的错误。该问题会间接影响数据库服务稳定性,可能加剧DNS解析或连接异常。

排查与解决方法

DNS解析问题排查与修复

  1. 监控Docker DNS服务状态:
    • 查看docker-dns进程资源占用及日志:
      ps aux | grep docker-dns
      journalctl -u docker | grep dns
      
    • 并发测试DNS解析:在多个app容器内同时执行nslookup db,观察是否出现失败。
  2. 调整容器DNS配置:
    • 在docker-compose.yml中为app服务配置外部公共DNS,绕过Docker内置DNS:
      services:
        app:
          dns:
            - 8.8.8.8
            - 1.1.1.1
      
    • 修改容器内/etc/resolv.conf,延长DNS超时时间和重试次数:
      options timeout=5 attempts=3 rotate
      
  3. 优化Docker网络配置:
    • 升级Docker至较新稳定版(如23.x系列),修复旧版本DNS并发缺陷。
    • 修改Docker daemon配置/etc/docker/daemon.json,优化DNS参数:
      {
        "dns-opts": ["timeout=5", "attempts=5"],
        "dns": ["8.8.8.8", "1.1.1.1"]
      }
      
    • 重启Docker服务生效:systemctl restart docker

共享内存问题排查与修复

  1. 检查/dev/shm空间:在宿主机执行df -h /dev/shm,确认内存文件系统剩余容量。
  2. 调整PostgreSQL共享内存参数:
    • 修改postgresql.conf中的shared_buffers、work_mem参数,避免过度申请内存。
    • 临时扩大/dev/shm挂载大小:
      mount -o remount,size=16G /dev/shm
      
    • 永久生效需修改/etc/fstab中/dev/shm的挂载参数。
  3. 监控宿主机内存使用:用top、htop工具实时监控内存占用,避免内存耗尽导致/dev/shm不足。

通用连接优化

  • 为SQLAlchemy添加连接重试逻辑,应对偶发的DNS解析失败:
    from sqlalchemy import create_engine
    from sqlalchemy.exc import OperationalError
    import time
    
    def create_retrying_engine():
        engine = create_engine("postgresql+psycopg2://postgres@db:5432/mydatabase")
        max_retries = 3
        for attempt in range(max_retries):
            try:
                with engine.connect():
                    return engine
            except OperationalError as e:
                if "Temporary failure in name resolution" in str(e) and attempt < max_retries -1:
                    time.sleep(1)
                    continue
                raise
    
  • 限制app实例的连接池大小,减少DNS查询频率和PostgreSQL连接压力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:35:24