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

来源:这里教程网 时间:2026-02-21 17:41:06 作者:

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 做节制拉取。

设置
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.Message
ev.Records[i].Body
是字符串,需手动 JSON 反序列化业务数据
删除动作由 Lambda 自动完成(只要没抛异常),但若需自定义重试策略,得改用
EventSourceMapping
并禁用自动删除

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

相关推荐