diff --git a/infra/docker/compose.yml b/infra/docker/compose.yml index 13e5abee8..39c7051d0 100755 --- a/infra/docker/compose.yml +++ b/infra/docker/compose.yml @@ -10,20 +10,25 @@ # API_IMAGE - API 镜像名称 (默认: xiaoxia-saas-api:dev) # WORKER_IMAGE - Worker 镜像名称 (默认: xiaoxia-saas-worker:dev) # WEB_IMAGE - Web 镜像名称 (默认: xiaoxia-saas-web:dev) -# WEB_DOCKERFILE - Web Dockerfile 路径 -# WEB_NGINX_CONF - Nginx 配置文件路径 # API_PORT - API 端口映射 (staging: 8000, production: 8001) # WEB_PORT - Web 端口映射 (staging: 3001, production: 3002) # GENERATED_FILES_HOST_DIR - 生成文件的主机目录 -# WORKER_CONCURRENCY - Worker 并发数 (默认: 4) +# GENERATION_CONCURRENCY - Generation worker 并发(用户实时任务,默认 2) +# TRANSCODE_CONCURRENCY - Transcode worker 并发(后台/转码/AI,默认 2) # WORKER_MAX_TASKS_PER_CHILD - Worker 每个子进程最大任务数 (默认: 100) +# BEAT_ENABLED - 容器内启动 celery beat(默认 1;独立 beat 容器部署设为 0) +# WORKER_CONCURRENCY - 兼容旧变量:未显式设置上面两个并发时按此总数分配 # -# 重要: +# 重要: # - 生产环境不要挂载 web-dist volume,否则会导致 403 # - 确保环境隔离网络已创建: docker network create xiaoxia-net-${ENV} -# - ENV=staging → xiaoxia-net-staging -# - ENV=production → xiaoxia-net-production +# - ENV=staging -> xiaoxia-net-staging +# - ENV=production -> xiaoxia-net-production # +# #2073 队列分流:worker 容器内跑三个独立进程——beat(只发定时任务)、 +# generation worker(只消费 generation 队列,实时高优)、transcode worker(消费 +# transcode + celery 队列,后台任务)。beat 不再嵌入 generation worker, +# 不占实时任务槽位;TRANSCODE_CONCURRENCY 独立伸缩,不再依赖 WORKER_CONCURRENCY 差值。 # =========================================== # 日志轮转配置(所有服务共享) @@ -40,53 +45,39 @@ services: # ========================================= api: image: ${API_IMAGE:-xiaoxia-saas-api:dev} - # 不在生产环境构建镜像,使用预构建的镜像 - # build: - # context: ../.. - # dockerfile: infra/docker/api.Dockerfile - container_name: xiaoxia-api-${ENV:-staging} restart: unless-stopped stop_grace_period: 30s stop_signal: SIGTERM - - # 环境变量文件(包含数据库密码等敏感信息) + env_file: - ../../.env - + environment: APP_ENV: ${APP_ENV:-staging} GENERATED_FILES_DIR: /app/generated GENERATED_FILES_URL_PREFIX: /generated-files PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://api.xiaoxiajianji.com} - - # 端口映射 - # Staging: 8000 -> 8000 - # Production: 8001 -> 8000 + ports: - "127.0.0.1:${API_PORT:-8000}:8000" - - # 共享生成文件目录 + 抖音 cookies 等运行时配置 + volumes: - generated-files:/app/generated - ../../deploy/configs:/app/configs:ro - + networks: - xiaoxia-net - - # 健康检查配置 + healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)"] interval: 30s timeout: 10s retries: 3 start_period: 40s - + logging: *default-logging - # ========================================= - # 资源限制建议(生产环境建议启用) - # ========================================= deploy: resources: limits: @@ -97,39 +88,48 @@ services: memory: 512M # ========================================= - # Worker 服务(Celery 任务队列) + # Worker 服务(#2073 队列分流:beat + generation + transcode 同容器三进程) # ========================================= + # 三个进程独立启动,任一退出则容器整体退出由 docker restart 拉起; + # 各自的并发与资源占用通过环境变量控制: + # - generation:GENERATION_CONCURRENCY(默认 2),消费 generation 队列 + # - transcode: TRANSCODE_CONCURRENCY(默认 2),消费 transcode,celery 队列 + # - beat: 不消费任务,只发定时任务到 celery 默认队列 worker: image: ${WORKER_IMAGE:-xiaoxia-saas-worker:dev} - + container_name: xiaoxia-worker-${ENV:-staging} restart: unless-stopped + # 长任务(ingest HEVC 转码最长 30min、生成硬超时 11min)给足优雅关闭窗口 stop_grace_period: 300s stop_signal: SIGTERM - + env_file: - ../../.env - + environment: APP_ENV: ${APP_ENV:-staging} + # 兼容旧变量:若两个 *_CONCURRENCY 均未显式设置,entrypoint 会按此总数分配 WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-4} WORKER_MAX_TASKS_PER_CHILD: ${WORKER_MAX_TASKS_PER_CHILD:-100} - # #1714 队列隔离:generation 队列独占 worker(默认并发 2),其余并发给转码 + # #2073 队列独立伸缩:generation 默认 2,transcode 默认 2(不再差值计算) GENERATION_CONCURRENCY: ${GENERATION_CONCURRENCY:-2} + TRANSCODE_CONCURRENCY: ${TRANSCODE_CONCURRENCY:-2} + # beat 默认在本容器启动;独立 beat 容器部署时设为 0 + BEAT_ENABLED: ${BEAT_ENABLED:-1} GENERATED_FILES_DIR: /app/generated GENERATED_FILES_URL_PREFIX: /generated-files PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://api.xiaoxiajianji.com} - + volumes: - generated-files:/app/generated - + networks: - xiaoxia-net - # 健康检查配置 - # 注:容器内无 pgrep/ps,扫描 /proc 所有进程的 cmdline 查找 celery 进程 + # 健康检查:至少有一个 celery worker 进程在跑(beat 本身不作为存活依据) healthcheck: - test: ["CMD-SHELL", "grep -lq celery /proc/[0-9]*/cmdline 2>/dev/null || exit 1"] + test: ["CMD-SHELL", "grep -q 'celery.*worker' /proc/[0-9]*/cmdline 2>/dev/null || exit 1"] interval: 30s timeout: 10s retries: 3 @@ -137,12 +137,8 @@ services: logging: *default-logging - # ========================================= - # 资源限制建议(生产环境建议启用) - # ========================================= - # 注意: Worker 需要处理视频,建议分配更多资源 - # #1714 队列隔离后容器内运行 generation + transcode 两个 worker 进程, - # 总并发 = WORKER_CONCURRENCY(默认 4),4C8G 以上确保视频渲染不 OOM + # 资源限制:容器总资源 = gen + trans + beat,按 2+2 并发场景建议 4C8G; + # 后续如需独立扩容/重启,可拆为 worker-generation / worker-transcode / worker-beat 三个 service。 deploy: resources: limits: @@ -157,35 +153,21 @@ services: # ========================================= web: image: ${WEB_IMAGE:-xiaoxia-saas-web:dev} - # 不在生产环境构建镜像,使用 web-artifact.Dockerfile - # build: - # context: ../.. - # dockerfile: ${WEB_DOCKERFILE:-infra/docker/web.Dockerfile} - # args: - # (NGINX_CONF no longer needed - all configs baked into image) - + container_name: xiaoxia-web-${ENV:-staging} restart: unless-stopped - - # 端口映射 - # Staging: 3001 -> 80 - # Production: 3002 -> 80 (通过 Nginx 反向代理) + ports: - "127.0.0.1:${WEB_PORT:-3001}:80" - + networks: - xiaoxia-net - - # ========================================= - # Nginx 配置运行时覆盖(双保险:entrypoint 也按 APP_ENV 选择配置) - # 确保容器使用正确环境的 nginx 配置,即使镜像构建时使用了默认配置 - # 注意: 只覆盖 /etc/nginx/conf.d/default.conf,不挂载 /usr/share/nginx/html - # ========================================= + environment: - APP_ENV=${ENV:-staging} volumes: - ./nginx-${ENV:-staging}.conf:/etc/nginx/conf.d/default.conf:ro - + healthcheck: test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:80"] interval: 30s @@ -194,9 +176,6 @@ services: logging: *default-logging - # ========================================= - # 资源限制建议 - # ========================================= deploy: resources: limits: @@ -212,9 +191,6 @@ volumes: driver_opts: type: none o: bind - # 重要: 确保主机目录存在且有正确权限 - # Staging: /var/lib/xiaoxia-saas-staging/generated - # Production: /var/lib/xiaoxia-saas-production/generated device: ${GENERATED_FILES_HOST_DIR:?GENERATED_FILES_HOST_DIR must be set in .env} # =========================================== @@ -223,8 +199,4 @@ volumes: networks: xiaoxia-net: external: true - # 网络名根据 ENV 变量区分,实现 staging/production 环境隔离 - # staging: xiaoxia-net-staging - # production: xiaoxia-net-production name: xiaoxia-net-${ENV:-staging} -