AWS IoT Python SDK订阅返回True但回调未触发问题排查
解决AWS IoT Python SDK订阅后收不到Lambda发布消息的问题
我之前也碰到过几乎一模一样的问题,折腾了好一阵子才解决,给你梳理几个最可能的排查方向和修复方案:
1. 确认订阅主题与发布主题完全匹配
AWS IoT的MQTT主题是大小写敏感的,而且通配符的使用必须严格对应:
- 比如Lambda发布的是
devices/pi-001/commands,树莓派如果订阅的是devices/+/commands(用了单层通配符+)是没问题的,但如果写成devices/#/commands(多层通配符#只能放在末尾)就会匹配失败; - 直接打印出树莓派代码里订阅的主题字符串,和Lambda控制台/代码里的发布主题做逐字符对比,确保没有拼写错误、斜杠位置不对的情况。
2. 把订阅逻辑放在连接回调里,确保重连后自动恢复订阅
很多人容易犯的错误是:在连接成功后只订阅一次,但如果树莓派的MQTT连接断开并自动重连,之前的订阅会丢失。正确的做法是把订阅逻辑放在on_connect回调函数里:
def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") # 每次连接(包括重连)后重新订阅主题 client.subscribe("your/target/topic", qos=1, callback=your_message_callback) # 初始化客户端时绑定连接回调 client.on_connect = on_connect
这样不管连接断开多少次,重连后都会自动重新订阅主题,不会错过消息。
3. 检查QoS等级的兼容性
Lambda发布消息的QoS和树莓派订阅的QoS需要兼容:
- 建议两边都暂时设置为QoS 1测试(QoS 1保证消息至少送达一次);
- 如果Lambda用QoS 2发布,而树莓派订阅用QoS 0,可能会出现消息无法正确传递的情况,先统一QoS等级再排查。
4. 验证IoT证书与策略的权限
虽然订阅返回True,但可能证书的权限不足导致无法接收消息:
- 检查附加到树莓派Thing的IoT策略,确保包含
iot:Subscribe和iot:Receive动作,且资源范围覆盖目标主题:{ "Effect": "Allow", "Action": [ "iot:Subscribe", "iot:Receive" ], "Resource": "arn:aws:iot:your-region:your-account-id:topic/your/target/topic" } - 同时确认证书已经激活,并且正确关联到了树莓派对应的Thing上。
5. 检查消息回调函数的定义是否正确
AWSIoTPythonSDK的消息回调函数必须严格符合参数要求,参数顺序或数量错误会导致回调无法触发(而且可能不会抛出明显异常):
正确的回调格式应该是:
def your_message_callback(client, userdata, message): print("Received message:") print(message.payload.decode("utf-8")) print(f"From topic: {message.topic}")
确保你的回调函数有且仅有这三个参数,顺序不能错。
6. 开启SDK调试日志,查看详细过程
在树莓派代码中开启调试日志,能帮你看到订阅、连接、消息接收的所有细节:
import logging # 配置SDK日志 logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) stream_handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') stream_handler.setFormatter(formatter) logger.addHandler(stream_handler)
运行代码后,查看日志中是否有Subscribed to topic...的成功提示,有没有收到消息的日志,或者权限不足、连接异常的错误信息。
我当时的问题就是连接重连后没有重新订阅,把订阅逻辑移到on_connect回调里就解决了。你可以按上面的顺序逐一排查,应该能找到问题所在。
内容的提问来源于stack exchange,提问作者kookcoder
相关产品推荐
相关产品推荐

