必须先用GetQueueUrlAsync获取真实队列URL,而非手拼;接收后须用ReceiptHandle调用DeleteMessageAsync删除,不可用MessageId;轮询应设WaitTimeSeconds节制,Lambda需用SQSEvent参数正确解析。
用 AwsSdkNet 发送 SQS 消息前,必须确认队列 URL 是否有效
很多人卡在第一步:调用 SendMessageRequest 报错 InvalidAddress 或 NotFound。这不是代码问题,而是没拿到真实队列 URL——它不是控制台里看到的“队列名称”,而是形如 https://sqs.us-east-1.amazonaws.com/123456789012/my-queue 的完整地址。你得先用 CreateQueue 或 GetQueueUrl 获取它,不能手写拼接。
- 推荐用
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 做节制拉取。