4. 事件网格高级过滤与重试
在事件驱动集成中,事件网格(Event Grid)承担的是“事件分发中枢”的角色。它并不保证每个事件都被业务系统成功处理,而是保证在既定策略下尽可能完成投递,并把无法投递的事件显式暴露出来。理解高级过滤、重试策略、指数退避与死信队列,是设计可靠事件链路的必修课。
一、事件筛选:在源头减少无效投递
事件网格支持两类过滤:事件类型过滤和主题过滤。事件类型过滤基于 eventType 字段,例如只订阅 Microsoft.Storage.BlobCreated;主题过滤则基于事件数据中的字段路径,例如 data.url、data.contentType 或自定义属性。主题过滤支持 StringIn、StringNotIn、StringBeginsWith、StringEndsWith、StringContains、NumberGreaterThan、BoolEquals 等操作符,并可通过 enableAdvancedFilteringOnArrays 对数组元素逐项匹配。
过滤的价值在于:把不符合业务条件的事件在订阅入口就丢弃,避免下游函数或队列被无关事件淹没。例如只处理 .jpg 与 .png 图片上传,可配置 data.url 以 .jpg 或 .png 结尾;若还要排除缩略图目录,可再加一条 data.url 不包含 /thumbnails/ 的条件。多个条件之间是“与”关系,同一字段的多个取值是“或”关系。
二、重试策略与指数退避
当订阅端返回非 2xx 响应、超时或无法连接时,事件网格会按重试策略重新投递。默认策略为:最多重试 30 次,采用指数退避,首次重试约在 10 秒后,之后间隔逐步拉长,最长可达数分钟。实际等待时间带有随机抖动,避免大量事件同时重试造成“惊群”。
重试策略可配置 maxDeliveryAttempts(1~30)、eventTimeToLiveInMinutes(1~1440 分钟)以及重试间隔。事件 TTL 决定事件在网格中保留的最长时间,超过 TTL 仍未成功投递的事件会被丢弃或转入死信。重试次数与 TTL 共同决定“最多尝试多久”:即使重试次数未用完,TTL 到期也会停止投递。
{
"retryPolicy": {
"maxDeliveryAttempts": 10,
"eventTimeToLiveInMinutes": 120
}
}
指数退避的意义在于给下游恢复时间。若下游因数据库连接池耗尽而短暂不可用,立即高频重试只会加剧拥塞;退避后重试可显著提高最终成功率。但退避也意味着事件延迟增加,因此对实时性要求高的链路,应把重试次数控制在较小范围,并配合死信队列快速暴露问题。
三、死信队列:让失败事件可追踪、可重放
死信队列(Dead-Letter Queue)用于存放无法成功投递的事件。启用后,事件网格会把最终失败的事件写入指定的存储容器(Blob Storage)。死信事件包含原始事件内容、失败原因、投递尝试次数、最后尝试时间等元数据,便于排查与重放。
死信队列不是“垃圾桶”,而是“待处理队列”。典型处理方式包括:人工检查失败原因、修复下游后批量重放、或将死信事件转入告警系统。若未启用死信队列,失败事件在 TTL 到期后会被静默丢弃,问题难以定位。
四、投递保障的整体关系
把过滤、重试、退避、TTL 与死信放在一起看,才能理解事件网格的投递保障模型:过滤决定“哪些事件进入投递”,重试与退避决定“投递多少次、间隔多久”,TTL 决定“最多保留多久”,死信决定“最终失败后去哪里”。下图展示了这一关系。
五、配置与验证要点
在 Azure 门户或 ARM/Bicep 模板中配置事件订阅时,需要同时关注过滤、重试与死信三部分。以下是一个事件订阅的配置片段示例,包含主题过滤、重试策略与死信设置:
{
"properties": {
"destination": {
"endpointType": "AzureFunction",
"properties": { "resourceId": "/subscriptions/.../functions/ProcessImage" }
},
"filter": {
"includedEventTypes": ["Microsoft.Storage.BlobCreated"],
"advancedFilters": [
{ "operatorType": "StringEndsWith", "key": "data.url", "values": [".jpg", ".png"] },
{ "operatorType": "StringNotContains", "key": "data.url", "values": ["/thumbnails/"] }
]
},
"retryPolicy": {
"maxDeliveryAttempts": 10,
"eventTimeToLiveInMinutes": 120
},
"deadLetterDestination": {
"endpointType": "StorageBlob",
"properties": {
"resourceId": "/subscriptions/.../storageAccounts/dlxstore",
"blobContainerName": "deadletter"
}
}
}
}
验证时,可先发送一条符合过滤条件的事件,确认订阅端收到;再发送一条不符合条件的事件,确认未被投递;然后模拟订阅端返回 500,观察重试次数与间隔是否符合预期;最后检查死信容器中是否出现失败事件及其元数据。通过这三类验证,可以确认过滤、重试与死信链路均按设计工作。