【问题标题】:Node.js sockets.io need for synchronization?Node.js sockets.io 需要同步吗?
【发布时间】:2020-07-31 00:27:33
【问题描述】:

我目前正在使用 node.js,使用 socket.io 库来实现一个简单的聊天应用程序。在这个应用程序中,出于不相关的原因,我想设置一个系统,在该系统中客户端可以向服务器请求一条信息。然后服务器将此请求广播到所有其他在线套接字,如果它们有答案,它们将响应。然后,服务器最终将它收到的(第一个)响应返回到发出请求的原始客户端套接字。

当然,客户端可能会收到多个响应,而只需要一个。因此,一旦收到一个,就应该丢弃其他的。但是,感觉我应该使用某种同步的数据结构/代码来确保“如果已收到答案”的检查按预期工作。

我已经对这个主题进行了一些搜索,但我看到过几次提到使用事件驱动模型并且不需要任何同步代码/数据结构的 node.js,因为没有多个线程。这是真的?我的场景是否不需要对同步进行任何特别关注,它会起作用吗?或者我是否需要使用一些同步方法,如果需要,使用哪些方法?

代码示例:

socket.on('new_response', async data => {
    await processResponse(data)
}); 

由于我正在使用加密,我必须使用 async/await,这使事情变得更加复杂。 processResponse 函数检查是否已经收到响应,如果没有,则处理它,否则忽略它。

【问题讨论】:

    标签: node.js socket.io synchronization thread-safety


    【解决方案1】:

    我会建议一些简单的方法,例如在每次广播中包含一个 uniqueID 给客户,询问他们是否有一条信息。然后,客户端在他们发送的任何响应中都包含相同的唯一 ID。

    这样,您的服务器可以从客户端接收答案,并跟踪它已经收到了哪些 uniqueID 值的答案,然后,如果已经收到该 uniqueID 的答案,那么它会忽略后面的响应的客户。

    uniqueID 是服务器端生成的,因此它实际上可以是一个不断增加的数字。您可以将目前使用的数字存储在服​​务器端 Set 对象中,以便您可以快速查找是否已收到该 uniqueID 的响应。

    然后,唯一剩下要做的就是在某个时间点将这些唯一 ID 在 Set 中老化掉,这样它们就不会永远累积。一个简单的方法是每 15 分钟左右用第二个 Set 对象替换 Set 对象,保留一个老一代,以便您可以同时检查它们。

    【讨论】:

    • 感谢您的回复。尽管该 Set 或检查是否已收到响应的代码段是否应该以任何方式同步,但这仍然提出了一个问题。例如,在 Scala 中,必须使用 SynchronizedMap 和/或在 if-test 周围使用 synchronized 关键字,以确保没有数据竞争。这也适用于这种情况吗?
    • @Arno - “以某种方式同步”是什么意思?你根本没有定义那是什么或意味着什么。你的问题是这样说的:“因此,一旦收到一个,其他的就应该被丢弃。”这就是我建议你如何让它工作的建议。因为 nodejs 在单个线程中运行您的 JS,所以从客户端返回的多个响应没有问题。这些将一次处理一个。
    • 我的意思是处理并发性。例如,如果 socket.io 将使用单独的线程处理每个传入消息,并且它们共享这个 Set 变量,则可能会发生数据竞争。这是我目前主要关心的问题。但是从您的回复中,我得出的结论是 node.js/socket.io 将按顺序处理每条传入消息?完全无需担心并发性,对吗?
    • @Arno - 是的,它将按顺序处理每个传入的请求。如果您在收到传入请求和使用共享 Set 对象之间有任何异步代码,那么您可能会遇到同时运行多个请求的时间问题,但您没有这样做一些异步的东西(并等待异步操作完成),那么您一次只会处理一个传入的请求。要更详细地评论,我们需要查看该代码。
    • @Arno - 现在回答你的问题了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多