BitzOrcas 使用 DotNetCore.CAP 作为事件总线,RabbitMQ 作为传输层,SQL Server 作为 Outbox 存储。这提供了恰好一次语义投递和事务保证。
架构
┌─────────────────────────────────────────────────┐│ 应用层 ││ CommandHandler → UoW.Commit() ││ │ │ ││ ▼ ▼ ││ 数据库写入 CAP PublishAsync() ││ │ │ ││ └────────────┬───────────────┘ ││ ▼ ││ SqlTransaction + CAP Outbox ││ (原子提交) │└─────────────────────┬───────────────────────────┘ ▼┌─────────────────────────────────────────────────┐│ CAP 内部(后台) ││ Outbox 表 → RabbitMQ → 消费者 │└─────────────┬───────────────────────────────────┘ ▼┌─────────────────────────────────────────────────┐│ 事件消费者 ││ CapSubscribe 处理器 → 服务方法 │└─────────────────────────────────────────────────┘CAP + SqlSugar 集成
核心集成点是 CapSqlSugarUnitOfWork:
// 在事务工作单元中发布await unitOfWork.PublishAsync(new NoteCreatedIntegrationEvent(noteId));await unitOfWork.PublishAsync(new NotificationRequestedEvent(userId, "Note created"));await unitOfWork.CommitAsync(); // 数据库 + Outbox 原子提交连接配置
{ "ConnectionStrings": { "Default": "Server=localhost;Database=BitzOrcas;..." }, "RabbitMq": { "Host": "localhost", "Port": 5672, "User": "guest", "Password": "guest" }}SqlSugar 和 EF Core 路径都使用 DotNetCore.CAP.SqlServer 作为 Outbox 表,使用 DotNetCore.CAP.RabbitMQ 进行消息传输。
集成事件契约
集成事件定义在 BitzOrcas.SaaS.Contracts 中——一个发布者和消费者都引用的独立程序集:
BitzOrcas.SaaS.Contracts/├── Auditing/ → 审计相关事件├── Catalog/ → 目录事件(计划、产品)├── Chat/ → 聊天消息事件├── Files/ → 文件上传/删除事件├── Notifications/ → 通知请求事件├── PlatformBilling/→ 计费/订阅/发票事件├── Tickets/ → 工单生命周期事件└── Webhooks/ → Webhook 事件信封事件发布
事件通过 INotificationPublisher 抽象发布:
public interface INotificationPublisher{ Task PublishAsync<T>(T @event, CancellationToken ct = default) where T : notnull;}- 默认:
NullNotificationPublisher(API Shell 模式,空操作) - 生产:
CapNotificationPublisher(通过 CAP 发布)
事件消费者
CAP 消费者使用 [CapSubscribe] 特性:
// 示例:Webhook 事件消费者public class WebhookPlatformEventConsumer{ [CapSubscribe("bitzorcas.webhook.*")] public async Task HandleAsync(WebhookEventEnvelope envelope) { // 路由事件到 Webhook 投递服务 }}Webhook 子系统
Webhook 投递系统是一个完整的”事件到 HTTP”桥接:
| 组件 | 用途 |
|---|---|
WebhookSubscriptionService | 管理订阅(CRUD + 密钥轮换) |
WebhookDeliveryService | 将事件投递到订阅者端点 |
WebhookRetryPolicy | 可配置限制的指数退避 |
IWebhookDeadLetterQueue | 投递失败跟踪 |
IWebhookIpAllowlistPolicy | 订阅者回调的 IP 限制 |
IWebhookRateLimitPolicy | 每订阅者投递限流 |
WebhookSignature | HMAC-SHA256 请求签名用于验证 |
Webhook 请求签名
每次 Webhook 投递包含签名头用于验证:
X-Webhook-Signature: sha256=abc123...X-Webhook-Timestamp: 2026-06-22T10:00:00ZX-Webhook-Event: ticket.createdX-Webhook-Subscription-Id: sub-789API Shell 模式
当未配置数据库/RabbitMQ 时,所有事件功能回退到 Null 实现:
NullNotificationPublisher— 静默丢弃已发布事件- 不注册 CAP 消费者 — 无后台处理
这使得 API 宿主可以在”Shell 模式”下运行,无需基础设施即可进行轻量级测试。