NodeJS + SocketIO 大套接字事件管理

NodeJS + SocketIO large socket event management

本文关键字:事件 管理 套接字 SocketIO NodeJS      更新时间:2023-09-26

我有一百万恐龙用户都登录了。

恐龙

希望看到其他恐龙何时实时更新它们的个人资料,因此它们被钩入 NodeJS/猫鼬模型:
dinosaur.schema.post('save', function (doc) { socket.emit('dinosaur:save', doc); });其中socket是连接的恐龙的插座。

恐龙也将看到其他几件事的实时更新。 也许是新闻、评论等。

那么,我的问题是,是否存在这种事件发出会变得很大并影响性能的情况?

在客户端,我会有类似socket.on('dinosaur:save', function(){})...我在不需要的时候摧毁听众。 但是,如果我听每一个dinosaur:save,理论上我可以处理一百万秒(比如说,如果每只恐龙都在同一秒内更新了它们的个人资料(。 似乎有一种更好的方法来处理大型数据集。

我想我可能还想看其他几个事件,我只是想知道是否有一些推荐的方法来进行这种套接字管理。

编辑:需要明确的是,我知道房间,但是例如,如果我有一个滚动列表,列出了我所在地区所有附近的恐龙,我可能只想接收所有dinosaur:save事件。 所以我仍然不确定。

通知一百万个任何东西都是很多数据包,如果你要通知的事情发生了很多,那就是很多,甚至比尝试在屏幕上显示更多。

通常首先要考虑的是:

  1. 这些通知的实时性如何? 是否可以将 60 秒或更长时间的通知批处理到每个用户每个通知周期的一个数据包中?

  2. 每个
  3. 用户真的必须看到每个其他用户的每一个变化吗? 您知道,任何用户界面都绝对不可能呈现一百万个其他用户的状态。 所以,我认为每个用户都不必知道每个其他用户的状态。 也许如果有 1-50 个其他用户,但如果有一百万,则不会。

  4. 您能否通过算法确定给定用户可能感兴趣的用户声明并仅向他们广播。 例如,您能否仅就地理位置靠近它们的其他用户保持最新状态?

  5. 能否有一个用户界面,用户可以告诉您他们要跟踪哪些其他用户,以便您只更新这些用户? 或者可能是他们告诉您的用户和对他们地理感兴趣的用户的某种组合。 关键是无论如何你都无法观看一百万用户,所以你将不得不发明一个显示比这少得多的 UI。

  6. 如果客户端尚未具有其他用户的状态,则始终可以拥有一个 UI,该 UI 将根据需要获取该状态,因此您不必为每个客户端中的所有百万用户保留状态(因为它不可能一次全部显示(。 如果用户浏览以查看他们还没有的一些内容,您只需通过套接字或 ajax 调用从服务器获取它。

  7. 哦,在你
  8. 所说的规模上,你可能需要将你的用户连接分散在几个服务器上,所以你也必须处理这种复杂性。

如果将来有人遇到这种情况,这就是问题和我当前的解决方案。

我们需要实时更新。 如果您在某人的个人资料页面上,并且更新它,请显示出来。 如果您正在查看某些迎合的结果集,例如用户配置文件,并且其中任何一个用户更新了他们的配置文件,请显示该结果集。 如果你在另一个页面上,并且有一些计数器更改,例如,你附近的用户,显示这一点。 但是,我们不会同时出现在所有这些页面上,因此在客户端,如果我不在其他页面上,我什至不想知道其他更改。 这个问题可能会导致我收到可能导致带宽问题的所有通知,以及一大堆不必要的套接字使用。

所以,我解决问题的方法是使用房间。 我使用房间而不是命名空间,因为命名空间通常用于访问同一套接字资源的两个相互不相交的应用程序。 房间也更适合这个应用程序。

我为每个用户个人资料页面创建了一个动态的动态房间。 当访问者打开配置文件页面时,客户端调用socket.emit("joinRoom", modelName + ":" + modelObj._id);,并在服务器上使用 socket.on('joinRoom', function(room) { socket.join(room); }); 处理该页面。 如果还没有房间,这会自动创建房间。 并将用户添加到其中。 模型名称可以是我们想要的任何名称。 这只是我如何划分房间的命名约定。 你可以称呼房间任何东西。 但重要的部分是最后的._id。 使用猫鼬,没有两个DB对象可以具有相同的._id,因此这保证了唯一的房间。

当此配置文件页面的所有者更新其信息时,我们会在服务器上调用: io.sockets.in('Dinosaur:' + doc._id).emit("Dinosaur:" + doc._id + ":updated", doc); 并使用 socket.on(modelName + ":" + modelObj._id + ":updated" , function(msg){ // do something })在客户端接收它

中提琴,我们只将这些必要的信息发送给感兴趣的客户。

--(一个单独的问题( --
使用这种方法,我们还可以提供与多个用户相关的数据。 如果我们有一个用户配置文件的迎合结果列表,对于每个配置文件,我们可以将当前用户添加到所有这些满足结果配置文件的房间中。(所以他们在一个属于 _id X、_id Y、_id Z 等的房间里。然后,当前用户将位于多个房间中,所有房间都反映了这些用户的即时更新,因此反映了整个迎合结果列表,无论它是什么列表(也许是"附近的恐龙"(。
另一种方法(尤其是在列表比较静态的情况下(是让套接字每 X 秒重新传递一次结果集,使用相同的套接字和相同的初始房间。