name: asyncapi-authoring description: 撰写和验证AsyncAPI 3.0规范,用于事件驱动API设计、消息代理和异步通信模式 allowed-tools: Read, Write, Edit, Glob, Grep, Bash
AsyncAPI 撰写技能
何时使用此技能
在以下情况下使用此技能:
- AsyncAPI 撰写任务 - 处理撰写和验证AsyncAPI 3.0规范,用于事件驱动API设计、消息代理和异步通信模式
- 规划或设计 - 需要AsyncAPI 撰写方法的指导
- 最佳实践 - 希望遵循已建立的模式和标准
概述
为事件驱动架构和异步通信模式撰写AsyncAPI 3.0规范。
AsyncAPI 3.0 结构
根文档
asyncapi: "3.0.0"
info:
title: "{服务名称} 事件 API"
version: "1.0.0"
description: |
用于{service}领域事件和命令的事件驱动API。
contact:
name: "{团队名称}"
email: "{team@company.com}"
license:
name: "MIT"
servers:
production:
host: "kafka.example.com:9092"
protocol: "kafka"
description: "生产Kafka集群"
security:
- $ref: "#/components/securitySchemes/sasl"
development:
host: "localhost:9092"
protocol: "kafka"
description: "本地开发环境"
defaultContentType: "application/json"
channels:
# 通道定义
operations:
# 操作定义
components:
# 可重用组件
通道 (AsyncAPI 3.0)
channels:
orderEvents:
address: "orders.events.{orderId}"
description: "订单生命周期事件的通道"
parameters:
orderId:
description: "订单唯一标识符"
schema:
type: string
format: uuid
messages:
orderCreated:
$ref: "#/components/messages/OrderCreated"
orderShipped:
$ref: "#/components/messages/OrderShipped"
orderDelivered:
$ref: "#/components/messages/OrderDelivered"
orderCancelled:
$ref: "#/components/messages/OrderCancelled"
orderCommands:
address: "orders.commands"
description: "订单命令消息的通道"
messages:
createOrder:
$ref: "#/components/messages/CreateOrderCommand"
cancelOrder:
$ref: "#/components/messages/CancelOrderCommand"
inventoryUpdates:
address: "inventory.updates.{productId}"
description: "实时库存级别更新"
parameters:
productId:
schema:
type: string
messages:
inventoryChanged:
$ref: "#/components/messages/InventoryChanged"
操作 (AsyncAPI 3.0)
operations:
# 发布操作(此服务发送)
publishOrderCreated:
action: send
channel:
$ref: "#/channels/orderEvents"
summary: "发布订单创建事件"
description: |
当新订单成功创建时发布。
消费者应使用此事件触发下游流程。
messages:
- $ref: "#/channels/orderEvents/messages/orderCreated"
tags:
- name: "orders"
- name: "lifecycle"
publishOrderShipped:
action: send
channel:
$ref: "#/channels/orderEvents"
summary: "发布订单发货事件"
messages:
- $ref: "#/channels/orderEvents/messages/orderShipped"
# 接收操作(此服务接收)
receiveCreateOrderCommand:
action: receive
channel:
$ref: "#/channels/orderCommands"
summary: "处理创建订单命令"
description: |
接收创建新订单的命令。
成功后将发布OrderCreated事件。
messages:
- $ref: "#/channels/orderCommands/messages/createOrder"
# 订阅操作
subscribeInventoryUpdates:
action: receive
channel:
$ref: "#/channels/inventoryUpdates"
summary: "订阅库存变更"
description: |
订阅实时库存更新。
用于维护本地库存缓存。
messages:
- $ref: "#/channels/inventoryUpdates/messages/inventoryChanged"
消息定义
components:
messages:
OrderCreated:
name: "OrderCreated"
title: "订单创建事件"
summary: "表示新订单已创建"
contentType: "application/json"
headers:
$ref: "#/components/schemas/EventHeaders"
payload:
$ref: "#/components/schemas/OrderCreatedPayload"
correlationId:
location: "$message.header#/correlationId"
traits:
- $ref: "#/components/messageTraits/commonHeaders"
OrderShipped:
name: "OrderShipped"
title: "订单发货事件"
summary: "表示订单已发货"
contentType: "application/json"
headers:
$ref: "#/components/schemas/EventHeaders"
payload:
$ref: "#/components/schemas/OrderShippedPayload"
traits:
- $ref: "#/components/messageTraits/commonHeaders"
OrderCancelled:
name: "OrderCancelled"
title: "订单取消事件"
summary: "表示订单已取消"
contentType: "application/json"
headers:
$ref: "#/components/schemas/EventHeaders"
payload:
$ref: "#/components/schemas/OrderCancelledPayload"
CreateOrderCommand:
name: "CreateOrderCommand"
title: "创建订单命令"
summary: "创建新订单的命令"
contentType: "application/json"
headers:
$ref: "#/components/schemas/CommandHeaders"
payload:
$ref: "#/components/schemas/CreateOrderPayload"
InventoryChanged:
name: "InventoryChanged"
title: "库存变更事件"
summary: "实时库存级别更新"
contentType: "application/json"
payload:
$ref: "#/components/schemas/InventoryChangedPayload"
负载模式
components:
schemas:
# 事件头部
EventHeaders:
type: object
required:
- eventId
- eventType
- timestamp
- version
properties:
eventId:
type: string
format: uuid
description: "唯一事件标识符"
eventType:
type: string
description: "事件类型名称"
timestamp:
type: string
format: date-time
description: "事件时间戳 (ISO 8601)"
version:
type: string
description: "事件模式版本"
example: "1.0"
correlationId:
type: string
format: uuid
description: "用于追踪的相关ID"
causationId:
type: string
format: uuid
description: "导致此事件的事件/命令ID"
CommandHeaders:
type: object
required:
- commandId
- commandType
- timestamp
properties:
commandId:
type: string
format: uuid
description: "唯一命令标识符"
commandType:
type: string
description: "命令类型名称"
timestamp:
type: string
format: date-time
correlationId:
type: string
format: uuid
userId:
type: string
description: "发起命令的用户"
# 事件负载
OrderCreatedPayload:
type: object
required:
- orderId
- customerId
- items
- totalAmount
- createdAt
properties:
orderId:
type: string
format: uuid
customerId:
type: string
format: uuid
items:
type: array
items:
$ref: "#/components/schemas/OrderItem"
totalAmount:
$ref: "#/components/schemas/Money"
shippingAddress:
$ref: "#/components/schemas/Address"
createdAt:
type: string
format: date-time
OrderShippedPayload:
type: object
required:
- orderId
- trackingNumber
- carrier
- shippedAt
properties:
orderId:
type: string
format: uuid
trackingNumber:
type: string
carrier:
type: string
enum:
- "fedex"
- "ups"
- "usps"
- "dhl"
estimatedDelivery:
type: string
format: date
shippedAt:
type: string
format: date-time
OrderCancelledPayload:
type: object
required:
- orderId
- reason
- cancelledAt
properties:
orderId:
type: string
format: uuid
reason:
type: string
enum:
- "customer_request"
- "payment_failed"
- "out_of_stock"
- "fraud_detected"
refundAmount:
$ref: "#/components/schemas/Money"
cancelledAt:
type: string
format: date-time
cancelledBy:
type: string
description: "取消订单的用户或系统"
# 命令负载
CreateOrderPayload:
type: object
required:
- customerId
- items
properties:
customerId:
type: string
format: uuid
items:
type: array
minItems: 1
items:
$ref: "#/components/schemas/OrderItemRequest"
shippingAddress:
$ref: "#/components/schemas/Address"
billingAddress:
$ref: "#/components/schemas/Address"
couponCode:
type: string
# 领域模式
OrderItem:
type: object
required:
- productId
- productName
- quantity
- unitPrice
properties:
productId:
type: string
format: uuid
productName:
type: string
quantity:
type: integer
minimum: 1
unitPrice:
$ref: "#/components/schemas/Money"
OrderItemRequest:
type: object
required:
- productId
- quantity
properties:
productId:
type: string
format: uuid
quantity:
type: integer
minimum: 1
Money:
type: object
required:
- amount
- currency
properties:
amount:
type: number
format: decimal
minimum: 0
currency:
type: string
pattern: "^[A-Z]{3}$"
example: "USD"
Address:
type: object
required:
- street
- city
- country
properties:
street:
type: string
city:
type: string
state:
type: string
postalCode:
type: string
country:
type: string
pattern: "^[A-Z]{2}$"
InventoryChangedPayload:
type: object
required:
- productId
- previousQuantity
- newQuantity
- reason
- changedAt
properties:
productId:
type: string
format: uuid
previousQuantity:
type: integer
newQuantity:
type: integer
reason:
type: string
enum:
- "sale"
- "return"
- "restock"
- "adjustment"
- "reservation"
changedAt:
type: string
format: date-time
消息特性和安全
components:
messageTraits:
commonHeaders:
headers:
type: object
properties:
x-trace-id:
type: string
description: "分布式追踪ID"
x-span-id:
type: string
description: "用于追踪的Span ID"
securitySchemes:
sasl:
type: scramSha256
description: "SASL/SCRAM-SHA-256认证"
apiKey:
type: apiKey
in: user
description: "API密钥认证"
oauth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: "https://auth.example.com/token"
scopes:
"events:publish": "发布事件"
"events:subscribe": "订阅事件"
serverBindings:
kafka:
schemaRegistryUrl: "https://schema-registry.example.com"
schemaRegistryVendor: "confluent"
AsyncAPI的C#模型
namespace SpecDrivenDevelopment.AsyncApi;
/// <summary>
/// 表示一个AsyncAPI 3.0规范文档
/// </summary>
public record AsyncApiSpec
{
public required string AsyncApi { get; init; } = "3.0.0";
public required AsyncApiInfo Info { get; init; }
public Dictionary<string, AsyncApiServer> Servers { get; init; } = [];
public string? DefaultContentType { get; init; }
public Dictionary<string, AsyncApiChannel> Channels { get; init; } = [];
public Dictionary<string, AsyncApiOperation> Operations { get; init; } = [];
public AsyncApiComponents? Components { get; init; }
}
public record AsyncApiInfo
{
public required string Title { get; init; }
public required string Version { get; init; }
public string? Description { get; init; }
public AsyncApiContact? Contact { get; init; }
public AsyncApiLicense? License { get; init; }
}
public record AsyncApiContact
{
public string? Name { get; init; }
public string? Email { get; init; }
public string? Url { get; init; }
}
public record AsyncApiLicense
{
public required string Name { get; init; }
public string? Url { get; init; }
}
public record AsyncApiServer
{
public required string Host { get; init; }
public required string Protocol { get; init; }
public string? ProtocolVersion { get; init; }
public string? Description { get; init; }
public List<Dictionary<string, List<string>>>? Security { get; init; }
public Dictionary<string, object>? Bindings { get; init; }
}
public record AsyncApiChannel
{
public required string Address { get; init; }
public string? Description { get; init; }
public Dictionary<string, AsyncApiParameter>? Parameters { get; init; }
public Dictionary<string, AsyncApiMessage>? Messages { get; init; }
public Dictionary<string, object>? Bindings { get; init; }
}
public record AsyncApiParameter
{
public string? Description { get; init; }
public AsyncApiSchema? Schema { get; init; }
public string? Location { get; init; }
}
public record AsyncApiOperation
{
public required OperationAction Action { get; init; }
public required AsyncApiChannelRef Channel { get; init; }
public string? Summary { get; init; }
public string? Description { get; init; }
public List<AsyncApiMessageRef>? Messages { get; init; }
public List<AsyncApiTag>? Tags { get; init; }
public List<Dictionary<string, List<string>>>? Security { get; init; }
public Dictionary<string, object>? Bindings { get; init; }
}
public enum OperationAction
{
Send,
Receive
}
public record AsyncApiChannelRef
{
public string? Ref { get; init; }
}
public record AsyncApiMessageRef
{
public string? Ref { get; init; }
}
public record AsyncApiMessage
{
public string? Name { get; init; }
public string? Title { get; init; }
public string? Summary { get; init; }
public string? Description { get; init; }
public string? ContentType { get; init; }
public AsyncApiSchema? Headers { get; init; }
public AsyncApiSchema? Payload { get; init; }
public AsyncApiCorrelationId? CorrelationId { get; init; }
public List<AsyncApiMessageTraitRef>? Traits { get; init; }
public Dictionary<string, object>? Bindings { get; init; }
}
public record AsyncApiCorrelationId
{
public string? Description { get; init; }
public required string Location { get; init; }
}
public record AsyncApiMessageTraitRef
{
public string? Ref { get; init; }
}
public record AsyncApiTag
{
public required string Name { get; init; }
public string? Description { get; init; }
}
public record AsyncApiSchema
{
public string? Type { get; init; }
public string? Format { get; init; }
public string? Description { get; init; }
public List<string>? Enum { get; init; }
public object? Default { get; init; }
public object? Example { get; init; }
public List<string>? Required { get; init; }
public Dictionary<string, AsyncApiSchema>? Properties { get; init; }
public AsyncApiSchema? Items { get; init; }
public int? MinItems { get; init; }
public int? MaxItems { get; init; }
public int? MinLength { get; init; }
public int? MaxLength { get; init; }
public decimal? Minimum { get; init; }
public decimal? Maximum { get; init; }
public string? Pattern { get; init; }
public List<AsyncApiSchema>? AllOf { get; init; }
public List<AsyncApiSchema>? OneOf { get; init; }
public List<AsyncApiSchema>? AnyOf { get; init; }
public string? Ref { get; init; }
}
public record AsyncApiComponents
{
public Dictionary<string, AsyncApiSchema>? Schemas { get; init; }
public Dictionary<string, AsyncApiMessage>? Messages { get; init; }
public Dictionary<string, AsyncApiParameter>? Parameters { get; init; }
public Dictionary<string, AsyncApiSecurityScheme>? SecuritySchemes { get; init; }
public Dictionary<string, AsyncApiMessageTrait>? MessageTraits { get; init; }
public Dictionary<string, AsyncApiOperationTrait>? OperationTraits { get; init; }
}
public record AsyncApiSecurityScheme
{
public required string Type { get; init; }
public string? Description { get; init; }
public string? In { get; init; }
public string? Name { get; init; }
public AsyncApiOAuthFlows? Flows { get; init; }
}
public record AsyncApiOAuthFlows
{
public AsyncApiOAuthFlow? ClientCredentials { get; init; }
}
public record AsyncApiOAuthFlow
{
public required string TokenUrl { get; init; }
public required Dictionary<string, string> Scopes { get; init; }
}
public record AsyncApiMessageTrait
{
public AsyncApiSchema? Headers { get; init; }
public string? ContentType { get; init; }
}
public record AsyncApiOperationTrait
{
public string? Summary { get; init; }
public string? Description { get; init; }
public List<AsyncApiTag>? Tags { get; init; }
}
事件设计模式
事件命名约定
event_naming:
format: "{聚合}{动作}"
past_tense_events:
description: "事件描述已发生的事情"
examples:
- "OrderCreated"
- "OrderShipped"
- "PaymentProcessed"
- "UserRegistered"
- "InventoryReserved"
command_naming:
format: "{动作}{聚合}Command"
examples:
- "CreateOrderCommand"
- "CancelOrderCommand"
- "ProcessPaymentCommand"
channel_naming:
pattern: "{领域}.{类型}.{资源}"
examples:
- "orders.events" (所有订单事件)
- "orders.events.{orderId}" (特定订单)
- "orders.commands" (订单命令)
- "inventory.updates.{productId}" (库存变更)
事件信封模式
event_envelope:
description: "所有事件的标准包装器"
structure:
metadata:
eventId: "UUID - 唯一事件ID"
eventType: "字符串 - 事件类型名称"
version: "字符串 - 模式版本"
timestamp: "ISO 8601时间戳"
correlationId: "UUID - 请求相关ID"
causationId: "UUID - 导致此事件的事件/命令ID"
source: "字符串 - 生产服务"
data: "实际事件负载"
example:
metadata:
eventId: "550e8400-e29b-41d4-a716-446655440000"
eventType: "OrderCreated"
version: "1.0"
timestamp: "2025-01-15T10:30:00Z"
correlationId: "660e8400-e29b-41d4-a716-446655440001"
source: "order-service"
data:
orderId: "order-123"
customerId: "customer-456"
totalAmount:
amount: 99.99
currency: "USD"
模式演化
schema_evolution:
strategies:
backward_compatible:
description: "新模式可以读取旧数据"
allowed_changes:
- "添加可选字段"
- "在末尾添加新枚举值"
- "扩展数字范围"
disallowed_changes:
- "移除必需字段"
- "更改字段类型"
- "重命名字段"
forward_compatible:
description: "旧模式可以读取新数据"
approach: "忽略未知字段"
full_compatible:
description: "双向兼容"
best_practice: "大多数系统的默认实践"
versioning:
header_based:
example: "version: '1.0'"
channel_based:
example: "orders.events.v2"
semantic:
format: "主版本.次版本"
major: "重大变更"
minor: "向后兼容的添加"
验证检查清单
asyncapi_validation_checklist:
structure:
- "有效的AsyncAPI 3.0.0语法"
- "所有必需字段存在"
- "没有未定义的$ref引用"
- "一致的命名约定"
channels:
- "清晰的通道寻址方案"
- "为动态通道定义参数"
- "所有引用的消息存在"
operations:
- "操作(发送/接收)正确指定"
- "通道引用有效"
- "提供摘要和描述"
- "分配适当的标签"
messages:
- "唯一的消息名称"
- "清晰的标题和摘要"
- "定义头部模式"
- "完整的负载模式"
- "需要时指定相关ID"
schemas:
- "列出所有必需字段"
- "指定类型和格式"
- "提供示例"
- "适当的验证约束"
security:
- "为生产环境定义安全方案"
- "操作指定安全需求"
documentation:
- "API描述解释目的"
- "提供联系信息"
- "所有环境的服务器URL"
参考资料
references/messaging-patterns.md- 事件驱动消息模式references/protocol-bindings.md- 协议特定配置
最后更新: 2025-12-26