【发布时间】:2018-12-28 17:09:59
【问题描述】:
我知道已经有很多这样的问题,但我找不到适合我的实现的问题。 我在 Node.js 环境中使用 redis,感觉 redis.publish 正在泄漏一些内存。我希望它是某种“背压”的东西,就像在这里看到的那样: Node redis publisher consuming too much memory
但据我理解:Node需要在同步上下文中释放这种压力,否则不会调用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 更好地跟踪内存引用并释放内存)
【问题讨论】: