在Cloud Run中以线程运行Selenium时出现Chrome无法访问错误
问题:Cloud Run多线程运行Selenium Chrome触发"chrome not reachable"错误
我的Web应用通过Threading后台运行耗时的Selenium流程(Chrome抓取数据写入数据库),本地Docker容器运行正常,Cloud Run串行运行也没问题,但Cloud Run+多线程组合会抛出错误:
selenium.common.exceptions.WebDriverException: Message: chrome not reachable
相关代码片段
routes.py
@app.route("/my_route", methods=['GET', 'POST']) def my_route(): search_term = 'search term' primary_key = session.get("primary_key") app = current_app._get_current_object() thread = threading.Thread(target=scrape_function, args=(search_term, primary_key, app)) thread.daemon = True thread.start() return render_template('my_route.html')
def scrape_function(search_term, primary_key, app): with app.app_context(): chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-dev-shm-usage') chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("--remote-debugging-port=9222") driver = webdriver.Chrome('/usr/local/bin/chromedriver', chrome_options=chrome_options) parsed_url = urllib.parse.quote(search_term) driver.get(f'https://google.com?search_query={parsed_url}') # Selenium搜索、页面跳转逻辑 url = driver.current_url driver.quit() user = User.query.filter_by(id=primary_key).first() user.url = url db.session.commit() print('Thread Completed') return url
Dockerfile
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY requirements.txt /code/ RUN pip install -r requirements.txt # 安装Google Chrome RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' RUN apt-get -y update RUN apt-get install -y google-chrome-stable # 安装ChromeDriver RUN apt-get install -yqq unzip RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/ # 设置显示端口 ENV DISPLAY=:99 COPY . /code/ CMD gunicorn --bind 0.0.0.0:8080 -w 3 run:app
解决方案
核心原因
- 端口冲突:固定
--remote-debugging-port=9222导致多线程启动Chrome时抢占同一端口,实例启动失败。 - Cloud Run CPU节流:默认请求结束后CPU会被暂停,后台线程无法继续运行Chrome。
- 资源竞争:Gunicorn多Worker+多线程导致容器资源过载,影响Chrome运行。
修复步骤
移除固定调试端口
删除chrome_options.add_argument("--remote-debugging-port=9222"),让Chrome自动分配端口,避免线程间端口冲突。同时推荐使用新版无头模式--headless=new提升稳定性:chrome_options = Options() chrome_options.add_argument('--headless=new') chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-dev-shm-usage') chrome_options.add_argument("--disable-gpu")配置Cloud Run CPU始终分配
在Cloud Run服务设置中,将「CPU分配」改为始终分配CPU,确保后台线程在请求返回后仍能获得CPU资源完成Selenium流程。调整Gunicorn Worker数量
Cloud Run单实例资源有限,建议将Gunicorn Worker数改为-w 1,避免多Worker与多线程的资源竞争:CMD gunicorn --bind 0.0.0.0:8080 -w 1 run:app确保资源释放
保持现有代码中driver.quit()的调用,确保每个线程结束后释放Chrome实例资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者B Hars
相关产品推荐
相关产品推荐

