内存存储的最佳方法(GCP/cloud 内存存储上的多区域)

best approach for in-memory storage (multi region on GCP/cloud memorystore)

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

我正在使用 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) 如何解决不同地域的虚拟机实例无法连接到redis实例的问题。我是否应该为我使用的每个区域(asia-east1、europe-north1、us-central1)创建一个 redis 实例,并镜像这 3 个 redis 实例,以便它们都具有相同的内容?

如果您有完全不同的方法,请告诉我!我仍在学习 nodejs 和 google 云平台,我愿意接受新的输入。

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

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

编辑 3: 我通过使用 haproxy 创建代理服务器来让它工作。该实例与redis实例位于同一区域。一个问题:会不会有性能问题?这真的是正确的方法吗?

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

Here you can find a really nice article about how to create a chat application wiht Cloud Pub/Sub. It is C# based, but the idea is the same, but using the Nodejs client libraries 查看有关 Pub/Sub 如何工作的一般架构:

此应用的架构将具有以下优点:

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

  • 不需要全服务器的传输方式
    发达

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

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