Files
kami_apple_exchage/backend/docs/playwright_singleton.md
danial 8ad2a5366a refactor(backend): 将Celery替换为Arq进行协程任务处理
本次提交将后端的任务队列系统从Celery迁移到了Arq,以支持基于协程的任务处理。主要改动包括:
- 更新文档和配置文件,反映架构变化。
- 修改健康检查和服务初始化逻辑,以适应Arq的使用。
- 移除与Celery相关的代码,并添加Arq任务定义和调度器。
- 更新Dockerfile和相关脚本,确保Arq worker能够正确运行。
- 调整API和业务服务中的任务处理逻辑,移除对Celery的依赖。

这些改动旨在提高系统的异步处理能力和整体性能。
2025-09-18 16:02:05 +08:00

5.2 KiB
Raw Blame History

Playwright单例模式实现说明

设计目标

  1. 全局共享一个browser实例使用context去区分操作的资源
  2. 手动初始化browserAPI服务不需要初始化worker中需要初始化
  3. 使用异步协程的方案去操作页面
  4. 引入task_state_manager记录每一步操作的百分比进度
  5. 支持Kubernetes分布式环境部署和Docker容器化

核心组件

1. DistributedPlaywrightManager (app/core/playwright_manager.py)

分布式单例模式的Playwright管理器负责

  • 全局共享一个browser实例
  • 管理多个browser context
  • 提供异步API操作页面
  • 集成进度跟踪功能
  • 针对Kubernetes环境优化
  • 支持Redis状态监控
# 使用示例
from app.core.playwright_manager import playwright_manager

# 初始化仅在worker中调用
await playwright_manager.initialize()

# 创建上下文和页面
page = await playwright_manager.create_page("context_id")

# 使用订单上下文管理器
async with playwright_manager.get_order_context(order_id) as context:
    page = context["page"]
    # 执行页面操作
    await page.goto("https://example.com")

# 关闭资源
await playwright_manager.close_context("context_id")
await playwright_manager.shutdown()

2. PlaywrightService (app/services/playwright_service.py)

业务服务层使用PlaywrightManager执行具体业务逻辑

  • 不再自己管理browser和context
  • 将处理流程拆分为多个步骤,便于进度跟踪
  • 集成task_state_manager更新任务状态

3. Worker初始化 (app/core/worker_init.py)

负责在worker启动时初始化Playwright在worker关闭时清理资源

  • 提供init_worker和shutdown_worker函数
  • 使用asyncio运行异步初始化函数

4. Arq集成 (app/core/arq_worker.py)

在Arq worker启动和关闭时调用初始化和清理函数

  • 使用on_startup回调初始化Playwright
  • 使用on_shutdown回调清理Playwright资源

Docker 部署配置

Dockerfile.worker 关键配置

# 使用稳定版本的 Playwright 镜像
FROM mcr.microsoft.com/playwright/python:v1.48.0-jammy

# 环境变量配置
ENV PLAYWRIGHT_BROWSERS_PATH=/app/playwright-browsers \
    GEVENT_SUPPORT=false  # 避免 Python 3.13 兼容性问题

# 安装必要的系统依赖
RUN apt-get update && apt-get install -y \
    libasound2-dev libxss1 libgconf-2-4 libxrandr2 libatk1.0-dev \
    libgtk-3-dev libgdk-pixbuf2.0-dev libxcomposite-dev libxcursor-dev \
    libxdamage-dev libxi-dev libxtst-dev libnss3-dev libcups2-dev \
    libxrandr-dev libasound2-dev libpangocairo-1.0-0 libgdk-pixbuf2.0-0 \
    libgtk-3-0 libgconf-2-4 libnss3 libxss1 libxtst6 fonts-liberation \
    libappindicator1 xdg-utils

# 安装 Playwright 浏览器(带重试机制)
RUN python -m playwright install chromium --with-deps || \
    python -m playwright install chromium || \
    echo "Playwright browser installation will be completed at runtime"

docker-entrypoint.sh 运行时检查

# 检查并安装 Playwright 浏览器仅针对worker服务
if [ "$SERVICE_TYPE" = "worker" ]; then
    echo "Checking Playwright browser installation..."

    # 运行时检查和安装
    if ! python -c "from playwright.sync_api import sync_playwright; ..."; then
        echo "Installing Playwright browsers..."
        python -m playwright install chromium --with-deps
    fi
fi

# 使用Arq worker进行异步任务处理
exec python -m arq app.core.arq_worker:ArqWorkerSettings \
    --max-jobs=${ARQ_MAX_JOBS:-10}

使用流程

  1. API服务启动时不初始化Playwright
  2. Worker服务启动时自动初始化Playwright
  3. 运行时检查Playwright浏览器安装状态
  4. 任务执行时使用PlaywrightService处理业务逻辑
  5. 任务执行过程中通过task_state_manager更新进度
  6. Worker关闭时自动清理Playwright资源

故障排除

常见问题

  1. 浏览器可执行文件未找到

    • 确保 PLAYWRIGHT_BROWSERS_PATH 环境变量正确设置
    • 运行时执行 python -m playwright install chromium
  2. Gevent 与 Python 3.13 兼容性问题

    • 使用 --pool=solo 替代 --pool=gevent
    • 设置 GEVENT_SUPPORT=false 环境变量
  3. 权限问题

    • 确保浏览器可执行文件有执行权限
    • 使用 find /app/playwright-browsers -type f -name "chrome" -exec chmod +x {} \;
  4. 系统依赖缺失

    • 安装所有必要的 GUI 库和字体
    • 使用 --with-deps 参数安装浏览器依赖

健康检查

# 检查 Playwright 是否正常工作
python -c "from playwright.sync_api import sync_playwright;
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True);
        browser.close();
        print('Playwright is working')"

优势

  1. 资源共享多个任务共享一个browser实例减少资源消耗
  2. 隔离性使用context隔离不同任务的操作
  3. 按需初始化:只在需要的环境中初始化,减少不必要的资源占用
  4. 进度跟踪:细粒度的进度跟踪,提高任务透明度
  5. 异步操作:使用异步协程提高并发性能
  6. 容器化支持完整的Docker部署方案支持Kubernetes
  7. 故障恢复:运行时检查和自动修复机制
  8. 监控集成Redis状态监控和健康检查