排课计算、课表发布、补考自动编排三类任务统一接入消息系统。

业务任务与 Outbox 消息同一事务落库,避免“数据库成功但消息没发出去”。
RabbitMQ 使用持久化消息、发布确认、手动 ACK、Quorum Queue、死信队列。
增加处理租约、心跳、异常重试、最大重试次数和幂等状态控制。
保留 InMemory 模式,开发环境无需安装 RabbitMQ。
支持多实例竞争消费,后续可以横向扩容。
新增 /health/messaging 消息系统健康检查。
This commit is contained in:
biss committed 2026-07-26 20:51:42 +08:00
1 parent 9f534c22f4
commit 6300645120
28 files changed
+6513 -313

No files matched your search

+3
View File
@@ -8,6 +8,9 @@ MYSQL_USER=jiaowu
MYSQL_PASSWORD= MYSQL_PASSWORD=
MYSQL_ROOT_PASSWORD= MYSQL_ROOT_PASSWORD=
RABBITMQ_USER=jiaowu
RABBITMQ_PASSWORD=
JWT_KEY= JWT_KEY=
ALLOWED_HOSTS=localhost ALLOWED_HOSTS=localhost
CORS_ORIGIN=http://localhost:8080 CORS_ORIGIN=http://localhost:8080
+10
View File
@@ -9,6 +9,16 @@ ConnectionStrings__MySql="Server=db.example.edu.cn;Port=3306;Database=jiaowu;Use
# Redis 是可选加速器;留空时应用仅使用进程内缓存。 # Redis 是可选加速器;留空时应用仅使用进程内缓存。
# ConnectionStrings__Redis="redis.example.edu.cn:6380,user=jiaowu,password=REPLACE_WITH_A_STRONG_PASSWORD,ssl=true,abortConnect=false" # ConnectionStrings__Redis="redis.example.edu.cn:6380,user=jiaowu,password=REPLACE_WITH_A_STRONG_PASSWORD,ssl=true,abortConnect=false"
# 单机可继续使用 InMemory;多实例生产部署建议启用 RabbitMQ。
BackgroundJobs__Transport=InMemory
# RabbitMq__HostName=rabbitmq.example.edu.cn
# RabbitMq__Port=5671
# RabbitMq__UserName=jiaowu
# RabbitMq__Password=REPLACE_WITH_A_STRONG_PASSWORD
# RabbitMq__VirtualHost=/jiaowu
# RabbitMq__UseTls=true
# RabbitMq__TlsServerName=rabbitmq.example.edu.cn
Cache__Enabled=true Cache__Enabled=true
Cache__KeyPrefix=jiaowu:v1 Cache__KeyPrefix=jiaowu:v1
Cache__ReferenceExpirationMinutes=30 Cache__ReferenceExpirationMinutes=30
+33
View File
@@ -223,6 +223,8 @@ SQLite 只用于本地开发:新库通过 `EnsureCreated` 建立,已有开
- `/health`、`/health/ready`:实际检查数据库连接,失败时返回 HTTP 503。 - `/health`、`/health/ready`:实际检查数据库连接,失败时返回 HTTP 503。
- `/health/cache`:检查可选 Redis;未配置 Redis 时返回 `disabled`,Redis - `/health/cache`:检查可选 Redis;未配置 Redis 时返回 `disabled`,Redis
故障不会影响数据库就绪探针。 故障不会影响数据库就绪探针。
- `/health/messaging`:检查后台任务传输;单机内存队列返回 `memory`,启用
RabbitMQ 时实际检查代理连接。
### 查询缓存与 Redis ### 查询缓存与 Redis
@@ -251,6 +253,37 @@ Redis 只作为可丢弃的查询缓存。连接失败时应用回源数据库
`allkeys-lfu` 淘汰策略,不启用持久化。`compose.app.example.yml` 不创建 Redis; `allkeys-lfu` 淘汰策略,不启用持久化。`compose.app.example.yml` 不创建 Redis;
如需连接外部 Redis,在 `.env` 中配置上述连接串即可。 如需连接外部 Redis,在 `.env` 中配置上述连接串即可。
### 后台任务与 RabbitMQ
自动排课、课表发布和补考自动生成使用数据库 Outbox 保存任务消息。创建业务任务与
Outbox 消息在同一次 MySQL 提交中完成,后台发布器再将消息投递给任务 Worker;重复
投递通过 Outbox 处理租约和唯一任务键抑制。任务状态表仍是前端查询进度与错误信息的
唯一来源。
开发和单机部署默认使用有界进程内队列,不需要 RabbitMQ:
```text
BackgroundJobs__Transport=InMemory
```
多实例生产部署应切换为 RabbitMQ,并配置独立账号、虚拟主机和 TLS:
```text
BackgroundJobs__Transport=RabbitMq
RabbitMq__HostName=rabbitmq.example.edu.cn
RabbitMq__Port=5671
RabbitMq__UserName=jiaowu
RabbitMq__Password=REPLACE_WITH_A_STRONG_PASSWORD
RabbitMq__VirtualHost=/jiaowu
RabbitMq__UseTls=true
RabbitMq__TlsServerName=rabbitmq.example.edu.cn
```
RabbitMQ 传输使用持久消息、发布确认、手动消费确认、每种任务独立队列和死信队列。
默认创建 Quorum Queue,重任务的消费者预取数为 1。MySQL 或 RabbitMQ 暂时不可用时,
未完成消息会根据 Outbox 状态和租约继续补投,消费者必须保持业务处理幂等。迁移服务
应先应用 `BackgroundJobOutbox` 数据库迁移,再启动应用实例。
## 跨平台发布与 Docker ## 跨平台发布与 Docker
`.gitea/workflows/publish.yml` 只在推送 `v*` 标签或手动运行时执行,普通分支 push `.gitea/workflows/publish.yml` 只在推送 `v*` 标签或手动运行时执行,普通分支 push
Loaded 3 of 28 files, more files were not shown because too many files have changed in this diff. Show more