真实案例分析:对于“异步、跨系统、多条件判定 + 延迟执行”场景的优雅架构设计 链接到标题


一、背景描述 链接到标题

在开发过程中,我们经常会遇到一类非常复杂的场景:

  • 需要根据 多条异步条件 判定是否执行一个操作
  • 各个条件条件依赖于多个 外部系统 API
  • 有时需要把 一个最终操作延迟执行 (如 24 小时后给用户发奖)
  • 事后对各步执行进行审计/日志记录

示例场景

当用户评价一件商品后,系统需要判断该用户是否符合奖励条件,如果是,则在 24 小时内给他的账户打入 1 美元


二、异步、多条件判断的主要难点 链接到标题

类型 描述
多条件上下文不同 每条条件可能需要用户ID/评论ID/商品ID之类
异步分开 每条条件需要调用不同服务无法合并
可扩展/可删除 要求后期可以自由地增删规则
延迟执行要求 奖励操作需要在所有判定通过后延迟执行

三、建议架构设计 链接到标题

流程图 (Mermaid) 链接到标题

flowchart TD A[用户提交评论] -->|Push Event| MQ[(Message Queue)] MQ --> Review[CommentReviewProcessor] Review --> R1[是否购买过该商品] Review --> R2[是否是第一次评论] Review --> R3[是否 24h 内评论过少于 10 项] Review --> R4[是否是 180 天内] Review --> R5[是否获得过奖励] Review --> R6[评论内容是否合法] R1 & R2 & R3 & R4 & R5 & R6 --> AllPass{All Passed?} AllPass -->|Yes| Schedule[延迟24h 执行奖励]

四、代码设计:分类规则 + DI 模式 链接到标题

规则接口 链接到标题

public interface ICommentRewardRule
{
    Task<RuleResult> EvaluateAsync(CommentContext context);
}

public class RuleResult
{
    public bool Passed { get; set; }
    public string? FailReason { get; set; }

    public static RuleResult Pass() => new RuleResult { Passed = true };
    public static RuleResult Fail(string reason) => new RuleResult { Passed = false, FailReason = reason };
}

上下文 CommentContext 链接到标题

public class CommentContext
{
    public string UserId { get; set; }
    public Guid ProductId { get; set; }
    public string Content { get; set; }
    public DateTime CommentTime { get; set; }
    public Guid CommentId { get; set; }
}

规则实现示例:是否购买过该商品 链接到标题

public class PurchasedProductRule : ICommentRewardRule
{
    private readonly IOrderApi _orderApi;

    public PurchasedProductRule(IOrderApi orderApi)
    {
        _orderApi = orderApi;
    }

    public async Task<RuleResult> EvaluateAsync(CommentContext context)
    {
        bool hasPurchased = await _orderApi.HasPurchasedProduct(context.UserId, context.ProductId);
        return hasPurchased ? RuleResult.Pass() : RuleResult.Fail("未购买商品");
    }
}

规则调用器 CommentRewardEvaluator 链接到标题

public class CommentRewardEvaluator
{
    private readonly IEnumerable<ICommentRewardRule> _rules;
    private readonly IRewardService _rewardService;

    public CommentRewardEvaluator(IEnumerable<ICommentRewardRule> rules, IRewardService rewardService)
    {
        _rules = rules;
        _rewardService = rewardService;
    }

    public async Task EvaluateAndRewardAsync(CommentContext context)
    {
        foreach (var rule in _rules)
        {
            var result = await rule.EvaluateAsync(context);
            if (!result.Passed)
            {
                Console.WriteLine($"[Rule Failed] {result.FailReason}");
                return;
            }
        }

        await _rewardService.GrantRewardAsync(context.UserId, 1.00m, context.CommentId);
    }
}

五、时序图解析 链接到标题

sequenceDiagram participant C as CommentController participant MQ as Message Queue participant P as CommentProcessor participant Rule as Rule Evaluator participant Ext as Order/Reward/Content APIs C->>MQ: Push CommentCreatedEvent MQ->>P: Receive Event P->>Rule: Evaluate Rules Rule->>Ext: Call Order API Rule->>Ext: Call Comment API Rule->>Ext: Call Reward API Rule->>Ext: Call Moderation API Rule-->>P: Result = All Passed P->>Ext: Schedule $1 reward via Reward API

六、延迟执行选项 链接到标题

  • Hangfire: 支持 Delay Job
  • Azure Function Timer / Storage Queue: 可以设置隐藏时间
  • Kafka 延迟队列
  • Quartz.NET: 非常经典的调度器

七、架构可维护性 链接到标题

能力 效果
增加/删除规则 规则为 DI + 组件化实现,无需更改主逻辑
异步/并发执行 本设计支持各规则异步调用,实现 Task.WhenAll 很简单
日志审计 每条规则可单独记录日志和失败原因
集成策略/缓存性 规则可加入内带缓存/定期刷新策略

八、结言 链接到标题

通过“规则链 + 异步执行 + 分层分类设计”,我们可以有效地应对后期任何规则变化、扩展需求和操作级延迟执行需求。

此架构特别适合如下场景:

  • 奖励分发系统
  • 评分/缓惊/认证系统
  • 分类操作应用(安全检测、网络监控)