mirror of
https://git.oceanpay.cc/danial/kami_apple_exchage.git
synced 2025-12-18 22:29:09 +00:00
本次提交将后端的任务队列系统从Celery迁移到了Arq,以支持基于协程的任务处理。主要改动包括: - 更新文档和配置文件,反映架构变化。 - 修改健康检查和服务初始化逻辑,以适应Arq的使用。 - 移除与Celery相关的代码,并添加Arq任务定义和调度器。 - 更新Dockerfile和相关脚本,确保Arq worker能够正确运行。 - 调整API和业务服务中的任务处理逻辑,移除对Celery的依赖。 这些改动旨在提高系统的异步处理能力和整体性能。
5.2 KiB
5.2 KiB
Playwright单例模式实现说明
设计目标
- 全局共享一个browser实例,使用context去区分操作的资源
- 手动初始化browser,API服务不需要初始化,worker中需要初始化
- 使用异步协程的方案去操作页面
- 引入task_state_manager,记录每一步操作的百分比进度
- 支持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}
使用流程
- API服务启动时不初始化Playwright
- Worker服务启动时自动初始化Playwright
- 运行时检查Playwright浏览器安装状态
- 任务执行时使用PlaywrightService处理业务逻辑
- 任务执行过程中通过task_state_manager更新进度
- Worker关闭时自动清理Playwright资源
故障排除
常见问题
-
浏览器可执行文件未找到
- 确保
PLAYWRIGHT_BROWSERS_PATH环境变量正确设置 - 运行时执行
python -m playwright install chromium
- 确保
-
Gevent 与 Python 3.13 兼容性问题
- 使用
--pool=solo替代--pool=gevent - 设置
GEVENT_SUPPORT=false环境变量
- 使用
-
权限问题
- 确保浏览器可执行文件有执行权限
- 使用
find /app/playwright-browsers -type f -name "chrome" -exec chmod +x {} \;
-
系统依赖缺失
- 安装所有必要的 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')"
优势
- 资源共享:多个任务共享一个browser实例,减少资源消耗
- 隔离性:使用context隔离不同任务的操作
- 按需初始化:只在需要的环境中初始化,减少不必要的资源占用
- 进度跟踪:细粒度的进度跟踪,提高任务透明度
- 异步操作:使用异步协程提高并发性能
- 容器化支持:完整的Docker部署方案,支持Kubernetes
- 故障恢复:运行时检查和自动修复机制
- 监控集成:Redis状态监控和健康检查