From 593a409fca5097cc4814de022b8e572cf6d9844f Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Fri, 16 Oct 2026 14:21:02 +0800 Subject: [PATCH] =?UTF-8?q?chore(=E9=83=A8=E7=BD=B2):=20=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E4=B8=8A=E8=AF=BE=E9=AB=98=E5=B3=B0=E6=97=B6=E7=BD=91?= =?UTF-8?q?=E9=A1=B5=E5=85=88=E4=BA=8E=E5=88=A4=E9=A2=98=E6=8B=BF=E5=88=B0?= =?UTF-8?q?=20CPU=EF=BC=8C=E5=86=85=E5=AD=98=E6=8C=A4=E6=BB=A1=E6=97=B6?= =?UTF-8?q?=E4=B8=8D=E5=85=88=E6=9D=80=E6=95=B0=E6=8D=AE=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 服务器 2 核 7.5G、没有 swap,和二十多个别的服务共用(空闲可用 3.5G): - postgres:shared_buffers 512MB(全库 249MB 能常驻)、work_mem 16MB、shm 256m、 oom_score_adj -500;事务空闲 60 秒断开 + TCP 保活,机房断网时锁不会挂两小时 - postgres、api 的 cpu_shares 加倍(按比例分、不封顶) - 判题沙箱、worker 内存上限 512m → 1g:最多六份同时编译、SQL 判题两个子进程都能顶满 512m Co-Authored-By: Claude Opus 5.5 --- docker/compose.debian.yml | 40 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/docker/compose.debian.yml b/docker/compose.debian.yml index ba1b51f..b318596 100644 --- a/docker/compose.debian.yml +++ b/docker/compose.debian.yml @@ -31,6 +31,36 @@ services: # 机房那套要连这个端口,必须对外暴露 ports: - "5445:5432" + # 这台机器 2 核 7.5G、没有 swap,和 gitea、judge0 等二十多个别的服务挤在一起(2026-10 实测 + # 可用 3.5G)。所以这里的取舍是「别被挤死」而不是「吃满内存」: + # - 全库 249MB,shared_buffers 512MB 能整库常驻,work_mem 16MB 让统计页的聚合排序不落盘; + # - oom_score_adj 压低:内存真满了,内核先杀别的,不先杀库; + # - cpu_shares 加倍:上课一个班同时交题时,查库和网页比判题、比别的服务先拿到 CPU。 + # 这是按比例分、不是封顶,闲的时候判题照样用满两个核; + # - 两个超时防机房断网:事务开着不动超过 60 秒就断,锁不会一直挂着; + # TCP 保活把断掉的远端连接从默认两小时缩到两分钟左右才发现。 + command: + - postgres + - -c + - shared_buffers=512MB + - -c + - effective_cache_size=2GB + - -c + - work_mem=16MB + - -c + - maintenance_work_mem=128MB + - -c + - idle_in_transaction_session_timeout=60s + - -c + - tcp_keepalives_idle=60 + - -c + - tcp_keepalives_interval=10 + - -c + - tcp_keepalives_count=6 + # 并行查询的工作区走 /dev/shm,docker 默认只给 64MB,大一点的并行哈希会直接报错 + shm_size: 256m + oom_score_adj: -500 + cpu_shares: 2048 healthcheck: test: ["CMD-SHELL", "pg_isready -U onlinejudge -d onlinejudge"] interval: 5s @@ -87,7 +117,10 @@ services: # 心跳路径跟着新后端改了:judge_server_heartbeat/ → judge-server/heartbeat BACKEND_URL: http://oj-api:3000/api/judge-server/heartbeat TOKEN: ${OJ2_JUDGE_TOKEN:?请在 docker/.env 里设置 OJ2_JUDGE_TOKEN} - mem_limit: 512m + # 同一时刻最多六份在编译(正式判题 2、试运行 2、提交前编译检查 2),g++ 编一份 iostream + # 峰值约 70MB、bits/stdc++.h 约 195MB,再加学生程序本身。512m 不够撑满,超了是容器里 + # 随机杀进程、学生看到系统错误 + mem_limit: 1g oj-api: build: &build @@ -127,6 +160,8 @@ services: retries: 3 start_period: 10s mem_limit: 512m + # 理由同 oj-postgres:上课时学生翻页、看结果要先于判题拿到 CPU + cpu_shares: 2048 oj-worker: build: *build @@ -140,7 +175,8 @@ services: environment: *api-env # 同一个镜像,换个子命令就是判题消费者 command: ["oj2-api", "worker"] - mem_limit: 512m + # SQL 判题的子进程各允许 512MB 数据段(judge/sql 的 ulimit -d),两个并发就能顶满 512m + mem_limit: 1g oj-web: build: