第二阶段优化已完成,重点是提高后台任务吞吐并降低 Outbox 数据库开销。

RabbitMQ 默认从单一回调通道提升为三类任务独立并行,跨类型并发能力由 1 提升到 3;每类还能独立配置 1–16 个消费者。[RabbitMqBackgroundJobs.cs (line 143)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/BackgroundJobs/RabbitMqBackgroundJobs.cs:143)
InMemory 开发模式同步改为按任务类型隔离队列,避免某类长任务堵塞其他任务。
租约恢复检查从“每发布一条执行一次”改为默认每 60 秒维护一次。
启动恢复改为数据库 NOT EXISTS 查询,不再把全部历史 Outbox 加载进内存。[BackgroundJobOutboxPublisher.cs (line 9)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/BackgroundJobs/BackgroundJobOutboxPublisher.cs:9)
完成消息默认保留 14 天,之后按每批 500 条清理,并增加对应组合索引。
/health/messaging 现在返回各状态积压量、过期租约和最老任务等待时间。[BackgroundJobMonitoringService.cs (line 16)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/BackgroundJobs/BackgroundJobMonitoringService.cs:16)
新增 Jiaowu.BackgroundJobs 运行时指标,覆盖发布量、处理量、发布耗时、处理耗时和清理量。[BackgroundJobTelemetry.cs (line 9)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/BackgroundJobs/BackgroundJobTelemetry.cs:9)
配置、Compose 和调优建议已更新。[README.md (line 257)](E:/jiaowu/README.md:257)
This commit is contained in:
2026-07-26 21:05:18 +08:00 Unverified
parent 6300645120
commit 034f1eacb8
21 changed files with 579 additions and 135 deletions
+38 -4
View File
@@ -137,7 +137,13 @@ if (!backgroundJobOptions.Transport.Equals(
if (backgroundJobOptions.PollIntervalMilliseconds is < 100 or > 30000 ||
backgroundJobOptions.LeaseSeconds is < 30 or > 3600 ||
backgroundJobOptions.PrefetchCount is < 1 or > 100 ||
backgroundJobOptions.AutomaticScheduleConcurrency is < 1 or > 16 ||
backgroundJobOptions.SchedulePublishConcurrency is < 1 or > 16 ||
backgroundJobOptions.MakeupExamAutoConcurrency is < 1 or > 16 ||
backgroundJobOptions.ProcessingAttemptLimit is < 1 or > 100 ||
backgroundJobOptions.MaintenanceIntervalSeconds is < 10 or > 3600 ||
backgroundJobOptions.CompletedRetentionDays is < 1 or > 3650 ||
backgroundJobOptions.CleanupBatchSize is < 10 or > 5000 ||
string.IsNullOrWhiteSpace(backgroundJobOptions.Exchange) ||
string.IsNullOrWhiteSpace(backgroundJobOptions.QueuePrefix))
{
@@ -269,6 +275,8 @@ builder.Services.AddScoped<ExamArrangementService>();
builder.Services.AddScoped<MakeupExamEligibilityService>();
builder.Services.AddScoped<MakeupExamArrangementService>();
builder.Services.AddScoped<MakeupExamAutoJobProcessor>();
builder.Services.AddSingleton<BackgroundJobTelemetry>();
builder.Services.AddScoped<BackgroundJobMonitoringService>();
builder.Services.AddSingleton<BackgroundJobRunner>();
if (backgroundJobOptions.UsesRabbitMq)
{
@@ -534,15 +542,41 @@ static async Task<IResult> CheckCacheHealthAsync(
static async Task<IResult> CheckMessagingHealthAsync(
IBackgroundJobTransport transport,
BackgroundJobMonitoringService monitoring,
CancellationToken cancellationToken)
{
var healthy = await transport.CheckHealthAsync(cancellationToken);
var backend = transport.IsDurable ? "rabbitmq" : "memory";
return healthy
? Results.Ok(new { Status = "healthy", Backend = backend })
: Results.Json(
new { Status = "unhealthy", Backend = backend },
try
{
var backlog = await monitoring.GetSnapshotAsync(cancellationToken);
return healthy
? Results.Ok(new
{
Status = "healthy",
Backend = backend,
Backlog = backlog
})
: Results.Json(
new
{
Status = "unhealthy",
Backend = backend,
Backlog = backlog
},
statusCode: StatusCodes.Status503ServiceUnavailable);
}
catch
{
return Results.Json(
new
{
Status = "unhealthy",
Backend = backend,
Backlog = (object?)null
},
statusCode: StatusCodes.Status503ServiceUnavailable);
}
}
public partial class Program;