ejabberd中流管理的奇怪错误

时间:2016-02-02 12:38:24

标签: xmpp ejabberd stream-management

我正在iOS上构建一个使用ejabberd的即时消息应用程序。我目前正在测试流管理功能,特别是在大多数情况下似乎有效的恢复。但是有一个我不明白的情况,我可以通过以下步骤进行复制,考虑到以下设置:resume_timeout:30,resend_on_timeout:if_offline

  • 在开始时客户端A和客户端B已连接,没有其他资源连接
  • 客户端B以不干净的方式崩溃或断开连接
  • 客户端A开始非常快速地发送一堆消息(10+)
  • ejabberd为发送的每条消息向A发送确认消息以确认消息已到达服务器
  • 坠机后大约20秒,B重新连接。此时A收到
  • 之前发送的每条消息的错误
<message xmlns="jabber:client" from="clientB@mydomain" to="clientA@mydomain/resourceID" type="error" id="CFBF4583-209A-4453-2567-CCCC7894827E">
   <body>test</body>
   <active xmlns="http://jabber.org/protocol/chatstates" />
   <request xmlns="urn:xmpp:receipts" />
   <error code="503" type="cancel">
       <service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
   </error>
</message>

我尝试使用ejabberd 16.01。

80%的时间都会发生这种情况;有时,A发送的消息会在30秒内重新连接时正确传送给B.

我的问题是:

  • 这种行为是否正确?如果已经收到消息的确认,我希望没有错误被反弹到客户端A.
  • 由于resend_on_timeout设置为if_offline且未连接其他资源,因此我预计不会出现任何错误。我是对的吗?

2 个答案:

答案 0 :(得分:2)

  • 流管理确认仅指示您的服务器已收到该消息。它并不意味着消息已被处理或传递到指定的地址。即使它被传递到该地址,该设备仍然可以返回该节的错误。
  • 这真的只是在黑暗中刺伤,但在浏览了ejabberd代码后,可能会发生这样的事情:

    1. clientB@mydomain/ResourceB删除了他们的连接,现在正在等待使用ResourceB恢复的会话。
    2. 客户端B重新连接,不恢复(因为它崩溃并丢失其状态)。
    3. 客户端B再次绑定资源ResourceB
    4. 现在服务器必须终止等待恢复的休眠会话,因为客户端B请求了相同的资源。
    5. 服务器检查是否有其他会话,因为它设置为if_offline
    6. 服务器看到有会话(新会话),因此选择退回而不是重发。
    7. 所以我的理论是if_offline只检查是否有其他会话需要处理未确认消息的队列,而不是在最初收到消息时。

答案 1 :(得分:1)

@xnyhps'的回答是正确的,我fixed这个特殊的角落案例用于下一个ejabberd版本。但是,@ xnyhps也是正确的,有其他极端情况,所以如果你想要可靠的消息传递,你应该使用XEP-0313。 XEP-0198的主要特征是会话恢复。