node.js - 内存存储的最佳方法(GCP/云内存存储上的多区域)
问题描述
我正在用 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 实例位于同一区域。一个问题:会不会有任何性能问题?这真的是要走的路吗?
解决方案
专注于您的第一个问题,我想说这种架构不是实现聊天应用程序的最佳方式。Google Cloud Platform 提供了非常强大的消息传递服务 - Pub/Sub。通过使用此服务,所有有关负载平衡、并发、连接和效率的问题都将在默认情况下得到解决。
在这里,您可以找到一篇关于如何使用 Cloud Pub/Sub 创建聊天应用程序的非常好的文章。它基于 C#,但想法是相同的,但使用Nodejs 客户端库 查看有关 Pub/Sub 工作方式的一般模式:
这个应用程序的架构将具有以下优点:
一对一(直接)和一对多消息传递功能
无需
开发完整服务器的传输方式
如果您不想使用 Pub/Sub,我仍然认为您将需要一个集中式服务器应用程序,该应用程序将能够与用户通信、处理他们的消息并将它们发送到正确的目的地和反向。
关于你的第二个问题,这可能有效,但我认为它可能会影响性能,更重要的是,系统本身的清晰度。维护、调试这样的东西将是一场噩梦。
推荐阅读
- javascript - Node jS express 验证 facebook API
- python - Django:在 HTML 表单提交上调用 views.py 中的函数
- python - 如何在主进程中获得信号以启动操作?
- proxy - 通过本地机器代理/隧道访问VPN
- algorithm - 如何找到完成 n 个作业的最少处理器数
- mysql - 如何在不使用预取概念的情况下从 mysql 反向外键获取数据?
- arrays - 将多个单元格的公式形成连接到一个单元格中
- django - pre_save 后保存模型会失败吗?
- teamcity - 是否可以使用不可用的 VCS 根运行 TeamCity 构建?
- pandas - 从 S3 读取时 AWS Lambda 函数出错