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

Django中Celery任务执行Selenium时出现连接池已满警告问题

解决Celery+Selenium Remote连接池耗尽警告

问题根源

这个"connection pool is full, discarding connection"警告,核心是HTTP连接池资源耗尽,和你用多线程共享Selenium Remote驱动的逻辑直接相关:

  • Selenium Remote驱动通过HTTP请求和Grid节点通信,每个元素操作都会建立新的HTTP连接
  • 主线程+守护线程同时操作同一个驱动,会并发创建大量连接,超出默认连接池的上限
  • Celery Worker自身的连接池配置和Selenium的连接池未协调,导致连接堆积无法及时释放

具体修复方案

1. 给Selenium配置自定义连接池

显式设置Selenium HTTP客户端的连接池大小,匹配你的线程数量(比如2-5,根据实际线程数调整):

from selenium import webdriver
from urllib3 import PoolManager

# 自定义连接池,限制最大连接数
http_client = webdriver.remote.remote_connection.HttpClient(
    pool_manager=PoolManager(maxsize=3)
)

# 创建Remote驱动时传入自定义客户端
driver = webdriver.Remote(
    command_executor="http://your-grid-host:4444/wd/hub",
    desired_capabilities=webdriver.DesiredCapabilities.CHROME,
    http_client=http_client
)

2. 给驱动操作加线程锁

主线程和守护线程共享驱动时,必须加锁避免并发操作导致的连接混乱和资源竞争:

import threading
from selenium.webdriver.common.by import By

driver_lock = threading.Lock()

# 守护线程的弹窗关闭逻辑
def popup_monitor(driver):
    while True:
        with driver_lock:
            try:
                close_btn = driver.find_element(By.XPATH, "//button[text()='关闭']")
                if close_btn.is_displayed():
                    close_btn.click()
            except Exception:
                pass
        time.sleep(1)

# 主线程操作驱动时同样加锁
with driver_lock:
    driver.find_element(By.ID, "username").send_keys("your-username")

3. 任务结束后彻底清理连接

任务执行完毕,必须确保驱动被正确关闭,同时清理连接池残留:

try:
    # 执行你的业务逻辑
    ...
finally:
    # 加锁关闭驱动,确保线程安全
    with driver_lock:
        driver.quit()  # quit会主动关闭所有和Grid的HTTP连接
    # 手动清理连接池(可选,进一步避免泄漏)
    http_client.pool_manager.clear()

4. 调整Celery Worker的连接池配置

在Celery配置文件中,优化Worker的连接池和进程设置,避免资源冲突:

# celery.py 或 Django settings.py
CELERY_WORKER_CONCURRENCY = 2  # 减少并发数,避免过多进程争抢连接
CELERY_WORKER_MAX_TASKS_PER_CHILD = 1  # 每个Worker进程处理完1个任务就重启,彻底清理连接
CELERY_BROKER_POOL_LIMIT = 10  # 增大Broker连接池上限

5. 优化弹窗处理逻辑(可选)

如果业务允许,尽量避免用守护线程,把弹窗检测整合到主线程的循环中,减少线程数:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 主线程中定期检查弹窗
while True:
    # 先处理弹窗(超时1秒,不阻塞主流程)
    try:
        close_btn = WebDriverWait(driver, 1).until(
            EC.element_to_be_clickable((By.XPATH, "//button[text()='关闭']"))
        )
        close_btn.click()
    except Exception:
        pass
    # 执行主业务操作
    driver.find_element(By.ID, "input-field").send_keys("content")
    # 根据业务逻辑设置退出条件
    if some_condition:
        break

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:17:36