You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ServiceBusSender的keep_alive属性作用及替代自定义Ping实现长连接的可行性问询

ServiceBusSender的keep_alive属性作用及替代自定义Ping实现长连接的可行性问询

提问者问题描述:

我正在尝试让ServiceBusSender的连接持续超过5分钟,不需要手动发送Ping消息。目前我用的是手动Ping的方式:

if time.time()-last_ping_time >= 200:
        logging.debug(f"trying to ping service bus {QUEUE_DATA['WorkersName']}")
        trash_message = ServiceBusMessage(b"")
        trash_message.application_properties = {b"SiteEnv":b"trash"}
        sender.send_messages(trash_message)
        last_ping_time=time.time()
        logging.debug("pinged service bus")

我想去掉这个逻辑,想知道是否可以通过给ServiceBusSender传递keep_alive属性(该属性在Configuration类中默认值为30),设置成1小时来解决问题?

更新1:

我了解到keep_alive本质是底层的Ping机制,但还是不确定:我能不能像下面这样使用它,然后移除自己的Ping逻辑,避免连接断开?

sender=ServiceBusSender._from_connection_string(topic_name="SOME_TOPIC_NAME",
                                                conn_str="SOME_CONNECTION_STRING",
                                                transport_type=TransportType.AmqpOverWebsocket,
                                                keep_alive=200)

更新2:

发现keep_alive只影响AMQP协议,不影响TCP层面...

更新3:

我查看了应用日志,发现Sender和Receiver初始化后长时间空闲才处理第一个请求,但第一个请求完成后15分钟就触发了ConnectionResetError。为什么会这样?如何让Sender和Receiver的连接在整个程序运行期间保持活跃,不需要手动发Ping消息?

日志内容:

2025-01-02 22:07:20,523 - DEBUG - got bool_launch_service_bus True so launching service bus
2025-01-02 22:07:20,523 - DEBUG - Launch time: 02/01/2025 22:07:20
2025-01-02 22:07:21,388 - INFO - RECEIVER: initiation was successful
2025-01-02 22:07:21,400 - INFO - SENDER: initiation was successful
2025-01-02 22:34:30,996 - DEBUG - Received request 
2025-01-02 22:34:30,997 - DEBUG - MessageId: id - CorrelationId id: 
2025-01-02 22:34:30,997 - DEBUG - Trying to call for CorrelationId: id
2025-01-02 22:34:30,997 - INFO - executing func()
2025-01-02 22:34:31,204 - DEBUG - Finished with CorrelationId: id time: 0.2070004940032959
2025-01-02 22:34:31,694 - DEBUG - full response creation time for id: 0.6970000267028809
2025-01-02 22:34:32,626 - INFO - finished id
2025-01-02 22:35:30,591 - INFO - RECEIVER: message with id: id complete by distributive service
2025-01-02 22:50:38,572 - DEBUG - Transport read failed: ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None)

专家解答:

看起来你在为ServiceBusSender的长连接维持问题费神,我来帮你理清关键要点:

1. keep_alive完全可以替代自定义Ping逻辑

你提到的keep_alive参数是SDK内置的AMQP心跳机制,默认30秒,它会在连接空闲时自动发送AMQP心跳帧,不需要你手动构造空消息。把它设置为合适的值(比如200秒或3600秒)后,完全可以移除你的自定义Ping代码——SDK会自动帮你完成保活动作,防止连接因空闲被服务端或中间设备断开。

2. 关于“keep_alive不影响TCP”的补充

这个认知没错,但不用过度焦虑:

  • TCP层面的保活一般由操作系统配置,而Azure Service Bus的核心连接逻辑基于AMQP,SDK的AMQP心跳已经能让防火墙、代理等中间设备识别到连接的活跃性,绝大多数场景下这就足够避免TCP连接被判定为空闲断开。
  • 如果你的运行环境有极其严格的TCP空闲超时规则,才需要额外配置系统级TCP keepalive,但这种情况非常少见,优先依赖SDK的AMQP keep_alive即可。

3. 针对日志中ConnectionResetError的解决建议

从日志来看,连接在第一次请求后15分钟左右断开,结合初始化后长时间空闲的情况,给你几个排查方向:

  • 升级SDK版本:旧版本的Azure Service Bus SDK可能存在keep_alive机制的bug,建议升级到最新稳定版,确保心跳逻辑正常执行。
  • 调整keep_alive间隔:当使用AmqpOverWebsocket时,部分代理/防火墙对WebSocket连接的空闲超时更敏感,与其设置1小时的长间隔,不如先尝试180-300秒(3-5分钟),更稳妥地避免被判定为空闲连接。
  • 复用Sender/Receiver实例:确保你的ServiceBusSender和ServiceBusReceiver是全局复用的单实例,不要频繁创建销毁——频繁重建连接反而更容易触发断开问题。

总结

完全可以通过配置keep_alive参数替代自定义Ping逻辑,只要确保SDK版本正确、参数设置合理、实例全局复用,就能让连接在整个程序运行期间保持活跃,不需要手动发送空消息。

备注:内容来源于stack exchange,提问作者Ivan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 11:58:09