node.js - Redis 发布内存泄漏?
问题描述
我知道已经有很多这样的问题,但我找不到适合我的实施的问题。我在 Node.js 环境中使用 redis,感觉 redis.publish 正在泄漏一些内存。我希望它是某种“背压”的东西,就像在这里看到的那样: Node redis 发布者消耗太多内存
但据我理解:Node需要在同步上下文中释放这种压力,否则不会调用节点事件循环,也不会调用GC。
我的程序如下所示:
const websocketApi = new WebsocketApi()
const currentState = {}
websocketApi.connect()
websocketApi.on('open', () => {
channels.map((channel) => websocketApi.subscribeChannel(channel))
})
websocketApi.on('message', (message) => {
const ob = JSON.parse(message)
if (currentState[ob.id]) {
currentState[ob.id] = update(currentState[ob.id], ob.data)
} else {
currentState[ob.id] = ob.data
}
const payload = {
channel: ob.id,
info: currentState[ob.id],
timestamp: Date.now(),
type: 'newData'
}
// when i remove this part, the memory is stable
redisClient.publish(payload.channel, JSON.stringify(payload))
})
// to reconnect in case of error
websocketApi.on('close', () =>
websocketApi.connect())
似乎消息之间的距离太近了,所以没有时间释放 redis.publish 中保存的字符串。
你知道这段代码有什么问题吗?
编辑:更具体地说,当我对我的应用程序进行内存转储时,我可以观察到什么:
内存由作为我的字符串化 JSON 有效负载的字符串和通过 Redis 本身发送的消息“块”组成。它们的 ref 保存在 redis 客户端中,保存在名为 chunk 的变量中。一些字符串有效载荷仍然被释放,但我创建它们的速度更快。
当我不通过 Redis 发布消息时,“currentState”变量会增长到某个点,然后不再增长。它显然对 RAM 有很大的影响,但这是意料之中的。其余的都很好,应用程序稳定在 400mb 左右,它会随着 redis 发布者而爆炸(PM2 重新启动它导致它达到最大 RAM 容量)
我在这里的感觉是我要求redis发布更多它可以处理的方式,而redis没有时间完成发布消息。它仍然包含所有上下文,因此它不会释放任何内容。我可能需要某种“队列”来让 redis 释放一些上下文并完成消息的发布。这真的有可能还是我疯了?
基本上,我程序中的每个循环都是“独立的”。是否有可能拥有与循环一样多的 redis 客户端?这是一个更好的主意吗?(恕我直言,节点是单线程的,所以不会有帮助,但它可能有助于 V8 更好地跟踪内存引用并释放内存)
解决方案
如果客户端由于尚未连接或连接失败或连接失败而未连接,redis 客户端会缓冲命令。
确保可以连接到 redis 服务器。确保您的程序已连接到服务器。我建议添加一个侦听器,redisClient.on('connect')
如果未发出,则客户端从未连接。
如果您已连接,客户端不应进行缓冲,但为了让问题尽快出现禁用离线队列,将选项传递enable_offline_queue: false
给createClient
此选项将导致在未连接时尝试发送命令失败。
您应该将错误侦听器附加到redisClient
: redisClient.on('error', console.error.bind(console))
。这可能会产生关于客户端为何缓冲的消息。
推荐阅读
- r - 如何在小标题中显示重复值?
- ios - 我可以创建一个可供多个 ContentView 使用的通用 ObservableObject 类吗?
- javascript - React Native 和 FlatList:试图获取超出范围索引 NaN 的框架
- python-3.x - AWS SSM 发送命令:参数参数未通过
- python - os.path.exists 在同一个文件上给出不同的结果
- r - R Plotly:aspectmode ='cube'不在3D散点图中使轴相等
- html - 正则表达式匹配和移动 HTML
- python - 我正在尝试写一个“如果那么”声明。如果 df['time'] 格式为 YYYY,则 df['time']=df['year']。否则 df['time']=df['date2']
- oracle - Oracle IF 存在 THEN, ELSE
- c# - 如何在门户 C# 应用程序功能中访问 Azure 功能中的应用程序设置?