Node.js   发布时间:2022-04-24  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了node.js – Websocket传输可靠性(重新连接期间Socket.io数据丢失)大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
用过的

NodeJS,Socket.io

问题

想象有2个用户U1& U2,通过Socket.io连接到一个应用程序。算法如下:

> U1完全失去Internet连接(例如关闭Internet)
> U2向U1发送消息。
> U1没有收到消息,因为互联网已关闭
>服务器通过心跳超时检测U1断开连接
> U1重新连接到socket.io
> U1从来没有收到来自U2的消息 – 它在步骤4中丢失了我猜。

可能的解释

我想我明白为什么会发生

> on步骤4服务器同时将套接字实例和消息队列杀死到U1
>此外在步骤5 U1和服务器创建新的连接(它不被重用),因此即使消息仍然排队,以前的连接仍然丢失。

需要帮忙

如何防止这种数据丢失?我必须使用听力,因为我不会有人永远挂在应用程序。此外,我还必须给一个可能性重新连接,因为当我部署一个新版本的应用程序,我想要零停机时间。

P.S。我称之为“消息”的东西不只是一个文本消息,我可以存储在数据库,但有价值的系统消息,哪些交付必须保证,或UI螺丝起来。

谢谢!

加法1

我已经有一个用户帐户系统。此外,我的应用程序已经很复杂。添加离线/在线状态不会有帮助,因为我已经有这样的东西。问题不同。

检查步骤2.在这一步,我们技术上不能说如果U1脱机,他只是失去连接,让说2秒,可能是因为互联网不好。所以U2给他一个消息,但是U1不接收它,因为互联网仍然为他(步骤3)。需要步骤4来检测离线用户,假设超时为60秒。最终在另一个10秒的互联网连接的U1是up,他重新连接到socket.io。但是来自U2的消息在空间中丢失,因为服务器U1由于超时而断开连接。

这是问题,我不会100%交货。

>在{}用户中收集一个emit(发射名称和数据),由随机emitID标识。发送emit
>确认在客户端发射(发送回带有emitID的服务器)
>如果确认 – 从{}通过emitID标识的对象被删除
>如果用户重新连接 – 检查{}这个用户,并循环通过它执行步骤1 {} {}中的每个对象。
>断开连接或/和连接flush {}为用户如有必要

解决方法

其他人在其他答案和评论暗示了这一点,但根本问题是Socket.IO只是一个交付机制,你不能依靠它单独的可靠交付。唯一知道消息已成功传递给客户端的人是客户端本身。对于这种系统,我建议做以下断言:

>消息不会直接发送到客户端;相反,它们被发送到服务器并存储在某种数据存储中。
>客户端负责在重新连接时询问“我错过了什么”,并且将查询数据存储中存储的消息以更新其状态。
>如果在连接接收方客户端时向服务器发送消息,则该消息将实时发送到客户端。

当然,根据应用程序的需要,你可以调整这些 – 例如,你可以使用一个redis列表或排序集合的消息,如果你知道一个事实,客户端上来清除它们至今。

这里有几个例子:

快乐路径:

> U1和U2都连接到系统。
> U2向U1应该接收的服务器发送消息。
>服务器将消息存储在某种持久性存储中,使用某种时间戳或顺序ID将其标记为U1。
>服务器通过Socket.IO将消息发送到U1。
> U1的客户端(可能通过Socket.IO回调)确认它接收到消息。
>服务器从数据存储中删除持久消息。

离线路径:

> U1失去互联网连接。
> U2向U1应该接收的服务器发送消息。
>服务器将消息存储在某种持久性存储中,使用某种时间戳或顺序ID将其标记为U1。
>服务器通过Socket.IO将消息发送到U1。
> U1的客户端不确认收到,因为他们离线。
>也许U2发送U1一些消息;它们都以相同的方式存储在数据存储器中。
>当U1重新连接时,它询问服务器“我看到的最后一条消息是X /我有状态X,我错过了什么。
>服务器根据U1的请求向U1发送U1从数据存储中丢失的所有消息
> U1的客户端确认收到,服务器从数据存储中删除这些邮件

如果你绝对需要保证交付,那么重要的是设计你的系统,连接的方式不重要,实时交付只是一个奖金;这几乎总是涉及某种数据存储。如在注释中提及的用户568109,存在抽象出所述消息的存储和传送的消息传递系统,并且可能值得研究这种预建的解决方案。 (你可能仍然需要自己编写Socket.IO集成)。

如果您不想将消息存储在数据库中,可以将它们存储在本地数组中;服务器尝试向U1发送消息,并将其存储在“待处理消息”列表中,直到U1的客户端确认接收到该消息。如果客户端离线,那么当它返回时,它可以告诉服务器“嘿我断开了,请给我任何我错过的”,服务器可以迭代这些消息。

幸运的是,Socket.IO提供了一种机制,允许客户端“响应”看起来像本机JS回调的消息。这里是一些伪代码

// server
pendingmessagesForSocket = [];

function sendmessage(messagE) {
  pendingmessagesForSocket.push(messagE);
  socket.emit('message',message,function() {
    pendingmessagesForSocket.remove(messagE);
  }
};

socket.on('reconnection',function(lastKNownmessagE) {
  // you may want to make sure you resend them in order,or one at a time,etc.
  for (message in pendingmessagesForSocket since lastKNownmessagE) {
    socket.emit('message',function() {
      pendingmessagesForSocket.remove(messagE);
    }
  }
});

// client
socket.on('connection',function() {
  if (prevIoUslyConnected) {
    socket.emit('reconnection',lastKNownmessagE);
  } else {
    // first connection; any further connections means we disconnected
    prevIoUslyConnected = true;
  }
});

socket.on('message',function(data,callBACk) {
  // Do something with `data`
  lastKNownmessage = data;
  callBACk(); // confirm we received the message
});

这与上一个建议非常相似,只是没有持久的数据存储。

您可能也对event sourcing的概念感兴趣。

大佬总结

以上是大佬教程为你收集整理的node.js – Websocket传输可靠性(重新连接期间Socket.io数据丢失)全部内容,希望文章能够帮你解决node.js – Websocket传输可靠性(重新连接期间Socket.io数据丢失)所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。