# 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 # 上游选股计划服务 (:8300) 跑在**宿主机本机**上。容器里访问宿主机的物理网卡 IP # (192.168.16.155) 会 ConnectTimeout —— docker 只给 FORWARD 链放行, 宿主机 INPUT 链 # 对 docker 网桥进来的包默认不放, 表现就是丢包超时 (不是 refused)。 # host-gateway 把宿主机在网桥上的地址 (172.x.0.1) 映射成 host.docker.internal, # 走这条路一般能通 (firewalld 会把网桥放在 docker zone, 默认 ACCEPT)。 # 还不通就是宿主机 INPUT 拦了 8300, 放行网桥网段即可: # sudo firewall-cmd --permanent --zone=trusted --add-source=172.16.0.0/12 && sudo firewall-cmd --reload extra_hosts: - "host.docker.internal:host-gateway" 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