0

我正在用 react-native 构建一个带有 nodejs 后端的聊天应用程序。我正在使用谷歌云平台。

我正在使用 websockets 在应用程序和后端之间创建连续连接。因为用户可以向特定客户端发送消息,所以我将套接字存储在 nodejs 中:

var sockets = {}
io.on('connection', socket => {
    console.log('user connected')
    let userId = socket.handshake.query.userId
    sockets[userId] = socket
    socket.on('message', msgData => {
        let msg = JSON.parse(msgData)
        sockets[msg.userId].emit('message', JSON.stringify(msg.message))
    }
    socket.on('disconnect', () => {
        console.log('user disconnected')
        delete sockets[userId]
    }
})

请注意,这是一个简化的示例。

问题是:我计划在负载均衡器后面的不同区域中拥有多个实例。当您连接到特定实例时,其他实例无法访问套接字对象。因此,当 2 个不同的用户连接到 2 个不同的实例时,他们无法互相聊天。

为了解决这个问题,我正在考虑将套接字存储在 redis 缓存(云内存存储)中。但是redis实例必须和VM实例在同一个区域。但就像我说的,我在多个区域有多个 VM 实例。

我的问题是:

1)这个解决方案是最好的方法吗?还是有其他可能性,例如将套接字存储在数据库中?

2)如何解决VM实例不在同一个区域时无法连接到redis实例的问题。我是否应该为我使用的每个区域(asia-east1、europe-north1、us-central1)创建一个 redis 实例,并镜像这 3 个 redis 实例,使它们都具有相同的内容?

另一方面,如果您有完全不同的方法,请告诉我!我还在学习 nodejs 和谷歌云平台,我对新的输入持开放态度。

编辑:所有实例(实例组)都在同一个 VPC 中。

编辑 2:如果我在与 redis 实例相同的区域中创建一个 VM,并将其用作代理怎么办?会不会有性能问题?

编辑 3:我通过使用 haproxy 创建代理服务器使其工作。该实例与 redis 实例位于同一区域。一个问题:会不会有任何性能问题?这真的是要走的路吗?

4

1 回答 1

2

专注于您的第一个问题,我想说这种架构不是实现聊天应用程序的最佳方式。Google Cloud Platform 提供了非常强大的消息传递服务 - Pub/Sub。通过使用此服务,所有有关负载平衡、并发、连接和效率的问题都将在默认情况下得到解决。

在这里,您可以找到一篇关于如何使用 Cloud Pub/Sub 创建聊天应用程序的非常好的文章。它基于 C#,但想法是相同的,但使用Nodejs 客户端库 查看有关 Pub/Sub 工作方式的一般模式:

在此处输入图像描述

这个应用程序的架构将具有以下优点:

  • 一对一(直接)和一对多消息传递功能

  • 无需
    开发完整服务器的传输方式

如果您不想使用 Pub/Sub,我仍然认为您将需要一个集中式服务器应用程序,该应用程序将能够与用户通信、处理他们的消息并将它们发送到正确的目的地和反向。

关于你的第二个问题,这可能有效,但我认为它可能会影响性能,更重要的是,系统本身的清晰度。维护、调试这样的东西将是一场噩梦。

于 2020-01-24T10:06:30.363 回答