C# AWS SQS消息处理方法 C#如何消费和发送SQS消息

2次阅读

必须先用GetQueueUrlAsync获取真实队列URL,而非手拼;接收后须用ReceiptHandle调用DeleteMessageAsync删除,不可用MessageId;轮询应设WaitTimeSeconds节制,Lambda需用SQSEvent参数正确解析。

C# AWS SQS消息处理方法 C#如何消费和发送SQS消息

AwsSdkNet 发送 SQS 消息前,必须确认队列 URL 是否有效

很多人卡在第一步:调用 SendMessageRequest 报错 InvalidAddressNotFound。这不是代码问题,而是没拿到真实队列 URL——它不是控制台里看到的“队列名称”,而是形如 https://sqs.us-east-1.amazonaws.com/123456789012/my-queue 的完整地址。你得先用 CreateQueueGetQueueUrl 获取它,不能手写拼接。

  • 推荐用 sqsClient.GetQueueUrlAsync(new GetQueueUrlRequest { QueueName = "my-queue" }) 动态获取,避免硬编码区域和账号 ID
  • 若跨区域访问,AmazonSQSClient 初始化时必须指定对应 RegionEndpoint,否则会默认走 us-east-1,导致 404
  • 消息体大小超 256KB?别硬塞——要么启用 S3 托管(用 AmazonSQSExtendedClient),要么提前拆分或压缩

ReceiveMessage 后不删消息,等于没处理

收到消息只是“暂取”,不是“消费完成”。SQS 默认保留消息(VisibilityTimeout 决定多久不可见),如果没显式调用 DeleteMessage,消息会在超时后重新入队,造成重复处理。这是生产环境最常被忽略的逻辑断点。

  • 务必在业务逻辑执行成功后,用 message.ReceiptHandle 调用 DeleteMessageAsync;失败则跳过删除,让消息重试
  • 不要用 message.MessageId 删除——它无效,只有 ReceiptHandle 是本次接收的唯一凭证
  • 批量接收(MaxNumberOfMessages > 1)时,每个消息要单独删,不能共用一个 ReceiptHandle

Polling + Delay 实现可靠轮询,别用死循环

官方 SDK 不提供“监听式”长连接 API,C# 端只能靠轮询。但直接 while(true) + Thread.Sleep(100) 会浪费 CPU、压垮队列、触发限流。正确做法是结合 VisibilityTimeout 和 WaitTimeSeconds 做节制拉取。

  • 设置 WaitTimeSeconds = 20(最长支持 20 秒),让请求挂起等待新消息,降低空轮询频次
  • 每次拉取后检查 Messages.count == 0,再 Sleep 1–5 秒,避免密集探测
  • 建议封装async Task PollAndProcessAsync(),配合 CancellationToken 支持优雅退出

Lambda 触发 SQS 时,C# 函数签名必须匹配事件结构

如果你把 C# 函数部署为 Lambda 并配置 SQS 触发器,SDK 自动生成的事件类型不是原始 Message,而是 SQSEvent。直接反序列化原始 Body 会丢掉 ReceiptHandle 和批处理元信息,导致无法删除。

  • 函数入口应为 public async Task FunctionHandler(SQSEvent ev, ILambdaContext context)
  • 每条 ev.Records[i].Sns.Messageev.Records[i].Body字符串,需手动 jsON 反序列化业务数据
  • 删除动作由 Lambda 自动完成(只要没抛异常),但若需自定义重试策略,得改用 EventSourceMapping 并禁用自动删除

C# 处理 SQS 最容易栽在“以为收了就是完了”,其实从 URL 获取、ReceiptHandle 生命周期、轮询节奏到 Lambda 事件包装,每层都有隐性契约。漏掉任意一环,轻则重复消费,重则消息积雪崩。

text=ZqhQzanResources