NodeJS + SocketIO大型套接字事件pipe理

我有一百万个恐龙用户全部login。

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

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

那么,我的问题是,在这种情况下,事件的发展将会变得越来越大,并影响到性能?

在客户端,我会有一些像socket.on('dinosaur:save', function(){}) …我不需要时摧毁侦听器。 但是,如果我正在听每一个dinosaur:save ,理论上我可以每秒处理一百万次(如果每一个恐龙都在同一秒更新他们的个人资料)。 看起来好像有一个更好的方式来处理大数据集。

我想有一些其他事件我可能想要看,我只是想知道是否有一些推荐的方法,这种套接字pipe理。

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

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

通常首先要考虑的事情是:

  1. 这些通知真的必须是实时的吗? 您能在每个通知期限内将60秒或更长时间的通知分批处理成每个用户一个分组吗?

  2. 每个用户是否真的必须看到来自其他用户的每一个变化。 你知道,任何用户界面都不能呈现一百万其他用户的状态。 所以,我认为每个用户不必知道其他用户的状态。 也许如果有1-50个其他用户,但是如果有一百万用户则不行。

  3. 你可以algorithm确定哪些用户状态一个给定的用户可能感兴趣,只有广播给他们。 例如,您是否可以只保留地理上靠近他们的其他用户?

  4. 你可以有一个用户界面,用户告诉你他们想跟踪哪些其他用户,所以你只更新这些? 或者也许是他们告诉你的用户和他们在地理上有趣的用户的组合。 问题是,无论如何你都不能看百万用户,所以你将不得不发明一个比那个用户还less得多的UI。

  5. 如果客户端还没有这个状态,你总是可以拥有一个UI来获取其他用户的状态,所以你不必为每个客户端的所有用户保留状态(因为它不能无论如何,可能都会立即显示)。 如果用户浏览以查看一些他们还没有的东西,那么只需通过套接字或ajax调用从服务器获取它。

  6. 呵呵,就你所说的规模来说,你可能需要把你的用户的连接分散到几台服务器上,所以你将不得不处理这个复杂的事情。

如果有人在将来遇到这个问题,这里是问题和我目前的解决scheme。

我们希望实时更新。 如果你在某人的个人资料页面,并且更新它,显示。 如果您正在查看某些用户configuration文件的结果集,并且其中任何一个用户都更新了其configuration文件,请显示该结果集。 如果你在另一个页面上,并且某个计数器发生了变化,比如说你附近的用户,那么就显示出来。 但是,我们不会同时在所有这些页面上,所以在客户端, 如果我不在其他页面上,我甚至不想知道其他更改 。 这是可能导致我被通知可能导致带宽问题的一切的问题,以及一大堆不必要的套接字使用。

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

我创build了一个dynamic的,在每个用户个人资料页面的飞行室。 当访问者打开一个configuration文件页面时,客户端调用socket.emit("joinRoom", modelName + ":" + modelObj._id); 并在与socket.on('joinRoom', function(room) { socket.join(room); }); 。 如果还没有,这会自动创build房间。 并添加用户。 modelName可以是我们想要的。 这只是我如何拆分房间的命名惯例。 你可以打电话给任何房间。 但最重要的部分是._id 。 使用Mongoose,没有两个DB对象可以有相同的._id ,所以这保证了独特的房间。

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

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

– (一个单独的问题) –
使用这种方法,我们也可以提供有关多个用户的数据。 如果我们有一个用户configuration文件的结果列表,对于每个configuration文件,我们可以将当前用户添加到所有这些结果configuration文件的房间中。 (所以他们在一个属于_id X, _id Y, _id Z等的房间中。当前的用户将会在多个房间中,全部反映这些用户的即时更新,并因此反映整个餐饮结果列表列表可能是(也许是“恐龙附近”)。
另一种方法,特别是如果列表更加静态的话,就是让套接字每隔X秒重新传递一次结果集,使用相同的套接字,以及相同的初始空间。