65 lines
2.3 KiB
YAML
65 lines
2.3 KiB
YAML
# tradingSystem (PMS) 容器编排
|
|
# 用法见 README「Docker 部署」。.env 放在本文件同目录 (服务器上手工维护, 不入库)。
|
|
# 三组服务:
|
|
# 默认 pms-web 管理页面 (38100)
|
|
# --profile sched pms-beat / pms-worker Celery 调度与执行
|
|
# --profile ws pms-ws QMT WebSocket 常驻连接 (协议 V1.0)
|
|
#
|
|
# pms-ws 与 worker 的关系: worker 里的 executor 把待发委托写进 pms_qmt_order 出口表,
|
|
# pms-ws 亚秒轮询取走并发出。两者**只经数据库耦合**, 谁先起谁后起都不影响 —— pms-ws 没起
|
|
# 来时 dispatcher 会因心跳陈旧而拒发, 指令保持原状, 不会静默堆在队列里。
|
|
|
|
x-pms-base: &pms-base
|
|
build: .
|
|
image: pms:latest
|
|
env_file: .env
|
|
environment:
|
|
- TZ=Asia/Shanghai
|
|
volumes:
|
|
- ./logs:/app/logs
|
|
restart: unless-stopped
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "5"
|
|
|
|
services:
|
|
pms-web:
|
|
<<: *pms-base
|
|
container_name: pms-web
|
|
command: uvicorn app.web.main:app --host 0.0.0.0 --port 38100
|
|
ports:
|
|
- "38100:38100"
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:38100/health', timeout=3)"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 10s
|
|
|
|
pms-beat:
|
|
<<: *pms-base
|
|
container_name: pms-beat
|
|
profiles: ["sched"]
|
|
command: celery -A app.scheduler.celery_app beat -l info
|
|
|
|
pms-worker:
|
|
<<: *pms-base
|
|
container_name: pms-worker
|
|
profiles: ["sched"]
|
|
command: celery -A app.scheduler.celery_app worker -l info -c 2
|
|
|
|
# QMT WebSocket 常驻连接。协议 §1 规定 PMS 只开一条连接 (多开会让指令乱序),
|
|
# 所以这个服务**绝不能扩副本** —— 不要 deploy.replicas, 不要 docker compose up --scale。
|
|
# 退出流程见 app/ws/runner.py 的 _shutdown: 刷水位 → 最后一次 ack → 关连接 → 清心跳,
|
|
# stop_grace_period 给足 25 秒是为了让这一串跑完; 强杀会丢掉最后一批 ack (不丢数据,
|
|
# 只是让 QMT 多留一会儿, 重连后按 last_seq 补发)。
|
|
pms-ws:
|
|
<<: *pms-base
|
|
container_name: pms-ws
|
|
profiles: ["ws"]
|
|
command: python -m app.ws.runner
|
|
stop_grace_period: 25s
|
|
stop_signal: SIGTERM
|