用户反馈「几个小时补充完成就行吧,几天也太慢了」——**对,是我把调度设得太保守**。
## 算一下原默认值有多离谱
30 个 / 30 分钟 = 60 个/小时 → 7,784 个要 **130 小时(5 天多)**
(我上一条说"3 天"还算乐观了。)
而**试水实测的吞吐**是 200 个 / 131 秒(并发 3)= **1.53 个/秒 ≈ 5,500 个/小时**。
**瓶颈根本不在查询速度,在我把调度频率设低了。**
## 新默认值:10 分钟一轮 × 400 个
400 个 × 0.65 秒 ≈ 4.4 分钟/轮
10 分钟一轮 → 2,400 个/小时 → 7,784 个约 **3.2 小时**
## ⚠️ 为什么不是更激进
查调度器源码发现一条**架构约束**(`run_due_jobs` 的注释写明):
作业串行执行 —— 目前只有 CK 巡检,单轮约 20~40 秒,远小于 tick
也就是**我的作业跑着的时候,CK 巡检/重登都得等着**(tick 5 分钟)。
所以一轮时长必须**明显小于间隔** —— 4.4 分钟 / 10 分钟是刻意留的余量。
一轮跑 6.5 分钟以上会把其他自动化作业饿住。
想更快有两条路(都需要你定):
1. 调大 `batch_size` —— 但**跑得越快越容易被风控**,而风控是全部账号一起受影响
2. 让调度器**并发跑作业**(目前是串行)—— 属另一处改动
## 验证
TZ=Asia/Shanghai **632 passed / 6 skipped**;ruff 全绿。
140 lines
4.6 KiB
Python
140 lines
4.6 KiB
Python
"""自动化调度:作业注册、调度线程与各作业实现。
|
||
|
||
登记作业请放在 ``register_default_jobs()``,由 ``main.py`` 在启动时调用一次,
|
||
避免 import 顺序影响注册结果。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from .jobs.account_overview_refresh import (
|
||
JOB_KEY as ACCOUNT_OVERVIEW_REFRESH_KEY,
|
||
)
|
||
from .jobs.account_overview_refresh import (
|
||
run_account_overview_refresh,
|
||
)
|
||
from .jobs.ck_health import JOB_KEY as CK_HEALTH_KEY
|
||
from .jobs.ck_health import run_ck_health
|
||
from .jobs.ck_relogin import JOB_KEY as CK_RELOGIN_KEY
|
||
from .jobs.ck_relogin import run_ck_relogin
|
||
from .jobs.douyu_tasks_retention import (
|
||
JOB_KEY as DOUYU_TASKS_RETENTION_KEY,
|
||
)
|
||
from .jobs.douyu_tasks_retention import (
|
||
run_douyu_tasks_retention,
|
||
)
|
||
from .jobs.points_expire import JOB_KEY as POINTS_EXPIRE_KEY
|
||
from .jobs.points_expire import run_points_expire_check
|
||
from .scheduler import (
|
||
JobSpec,
|
||
automation_enabled,
|
||
ensure_jobs,
|
||
register_job,
|
||
registered_jobs,
|
||
reset_registry,
|
||
run_due_jobs,
|
||
run_job_now,
|
||
scheduler_status,
|
||
start_scheduler,
|
||
stop_scheduler,
|
||
)
|
||
|
||
__all__ = [
|
||
"ACCOUNT_OVERVIEW_REFRESH_KEY",
|
||
"CK_HEALTH_KEY",
|
||
"CK_RELOGIN_KEY",
|
||
"DOUYU_TASKS_RETENTION_KEY",
|
||
"POINTS_EXPIRE_KEY",
|
||
"JobSpec",
|
||
"automation_enabled",
|
||
"ensure_jobs",
|
||
"register_default_jobs",
|
||
"register_job",
|
||
"registered_jobs",
|
||
"reset_registry",
|
||
"run_account_overview_refresh",
|
||
"run_ck_health",
|
||
"run_ck_relogin",
|
||
"run_douyu_tasks_retention",
|
||
"run_due_jobs",
|
||
"run_job_now",
|
||
"run_points_expire_check",
|
||
"scheduler_status",
|
||
"start_scheduler",
|
||
"stop_scheduler",
|
||
]
|
||
|
||
|
||
def register_default_jobs() -> None:
|
||
"""登记内置作业(幂等)。"""
|
||
register_job(
|
||
JobSpec(
|
||
key=POINTS_EXPIRE_KEY,
|
||
title="积分到期补记",
|
||
# 每天一次足够:到期时刻的精度是「天」级别,晚几小时记也不影响
|
||
interval_seconds=24 * 3600,
|
||
batch_size=200,
|
||
concurrency=1,
|
||
run=run_points_expire_check,
|
||
)
|
||
)
|
||
register_job(
|
||
JobSpec(
|
||
key=DOUYU_TASKS_RETENTION_KEY,
|
||
title="任务日志清理",
|
||
# 一天一次足够:这是**清理**,不是业务;跑太勤只是白扫索引。
|
||
interval_seconds=24 * 3600,
|
||
batch_size=2000,
|
||
concurrency=1,
|
||
run=run_douyu_tasks_retention,
|
||
)
|
||
)
|
||
register_job(
|
||
JobSpec(
|
||
key=CK_RELOGIN_KEY,
|
||
title="CK 自动重登",
|
||
# interval_seconds 同样是「同一行多久重试一次」的兜底(真实节奏由
|
||
# relogin_next_at 的退避表决定);批次小、跑得慢,单轮 10 条。
|
||
interval_seconds=6 * 3600,
|
||
batch_size=10,
|
||
concurrency=3,
|
||
run=run_ck_relogin,
|
||
)
|
||
)
|
||
register_job(
|
||
JobSpec(
|
||
key=ACCOUNT_OVERVIEW_REFRESH_KEY,
|
||
title="账号资料定时补全",
|
||
# 每 10 分钟一轮、每轮 400 个。
|
||
#
|
||
# 依据是**试水实测**,不是拍脑袋:200 个并发 3 跑了 131 秒
|
||
# = **1.53 个/秒 ≈ 5,500 个/小时**。瓶颈不在查询速度,而在调度频率。
|
||
# 400 个 × 0.65 秒 ≈ **4.4 分钟**跑完,10 分钟一轮
|
||
# = **2,400 个/小时**,7,784 个约 **3.2 小时**补完。
|
||
#
|
||
# ⚠️ 一轮时长必须**明显小于间隔**:调度器是**串行**的
|
||
# (见 scheduler.run_due_jobs 的注释:作业一个一个跑),
|
||
# 我的作业跑着的时候 CK 巡检/重登都得等着。所以宁可轮次多一些,
|
||
# 也不要一轮跑太久 —— 4.4 分钟 / 10 分钟是刻意留出的余量。
|
||
#
|
||
# 想更快就调大 `batch_size`(账号列表里那套),但**跑得越快越容易被风控**,
|
||
# 而风控是所有账号一起受影响。
|
||
interval_seconds=10 * 60,
|
||
batch_size=400,
|
||
concurrency=3,
|
||
run=run_account_overview_refresh,
|
||
)
|
||
)
|
||
register_job(
|
||
JobSpec(
|
||
key=CK_HEALTH_KEY,
|
||
title="CK 自动巡检",
|
||
# interval_seconds = 单账号多久重新检测一次(不是作业周期;
|
||
# 作业每个 tick 都跑)。全库 12,881 条按 5 分钟一轮、单轮 200 条
|
||
# 反推,吞吐 40 条/分钟,够 6 小时内覆盖一遍(规划 §7.3)。
|
||
interval_seconds=6 * 3600,
|
||
batch_size=200,
|
||
concurrency=5,
|
||
run=run_ck_health,
|
||
)
|
||
)
|