0

我知道像这样的问题可能是一个见仁见智的问题,这就是我试图提供更多细节的原因。

我正在开发具有以下“功能”的 WebSocket 服务器应用程序:

  • 2-3个连接可以指向同一个用户
  • 用户有时可以相互交互。无论是突发还是连续数据交换
  • 部分全局数据应始终在所有用户之间同步
  • 部分全局数据应该在一些用户之间延迟(按需)同步

想到2个可能的结构:

  1. 工作线程。主线程处理所有网络 IO、连接-> 用户绑定以及存储/与全局数据交互。它还会向工作线程发送大量-spostMessage。当来自不同线程的 2 个玩家需要交互时,工作线程偶尔会相互交谈。可能的问题:
    • postMessage开销(主要来自我所理解的序列化)。理论上,对于大多数消息我可以尝试使用SharedArrayBuffer. 我不认为它可以在此之外进行优化。
    • 主线程将处理网络 IO 和全局数据交互。也许这会成为瓶颈?
  2. 无状态 NodeJS 集群,将所有数据存储在 Redis 中,并利用偶尔锁定。问题/疑问:
    • 会使用更多的内存
    • 不管 Redis 有多快,与它的通信很可能会比使用postMessage-s 慢。
    • 多台服务器真的会有用吗?听说将同一种类型的 IO 拆分成多个进程是个坏主意。或者至少不如使用本机 Node 异步 IO 有利。
    • 我不认为有一种方法可以基于用户 id 之类的东西来捆绑连接。
    • 根据请求获取和设置 Redis 数据很好。但是一个进程如何知道某个键是否被另一个进程修改了呢?
4

1 回答 1

1

听起来您可能正处于设计阶段,还没有可以测量的运行代码。如果是这种情况,不要假设您知道瓶颈在哪里,并花时间设计和实施尚未测量的问题。性能瓶颈通常不在您认为的位置。如果您错了,花大量时间实现更复杂的架构来解决您认为可能存在瓶颈的地方很容易浪费大量的开发时间。

相反,实施更简单的架构甚至是原型,并大规模测试和测量。找出你真正的瓶颈在哪里。然后,您将确保您专注于正确的问题,并且将拥有一个测试引擎,您可以在实施替代方案时对其进行测量,以查看您的表现如何。

如果您问题的主要焦点是解决代码中的 CPU 密集型操作,我可能会首先探索使用工作线程和作业队列。仍然有一个 webSockets 连接到的主要进程,以及你保存所有状态的地方。

当请求进来时,创建一个作业并将其放入作业队列中(作业队列可以只是一个等待处理的作业对象数组)。如果有空闲线程,则从作业队列中获取最旧的作业并将该作业发送给该线程。它将以它需要的任何 CPU 密集型方式对其进行处理。当它完成时,它会将结果发送回您的主线程,然后您的主线程将下一个作业发送给它,并对结果执行任何需要的操作。

您可以拥有与 CPU 内核一样多的工作线程(超过这个数量会降低效率)。

该架构尝试将 CPU 密集型操作本地化并将它们分配给工作线程,同时保持架构的其余部分(您的 webSocket 连接和状态管理)相同,以使事情尽可能简单。

如果 CPU 密集型操作需要访问大量状态,那么您可能希望将状态移动到数据库,在该数据库中可以管理对状态的多线程访问(这是数据库有)。如果状态不是持久的,则数据库可能是 Redis。这通常比同步架构更受欢迎,因为在更新状态时管理并发并以任何一般方式进行同步可能不是您想要自己实现的东西(这是一个难题)。

于 2022-02-11T16:09:07.290 回答