nodejs 中大量短时间定时器实现方案?

2017-12-06 11:12:27 +08:00
 imherer

最近用 node+socket.io 做手游服务端,在小范围的线上测试的时候发现有内存泄漏,一开始是以为是 socket.io 的问题 最后这几天通过 heapdump 分析,基本定位了是node-scheduled这个库导致的(不知道是不是我使用问题)

heapdump 分析

程序刚启动打一个 snapshot,运行 3 个小时左右再打一个 snapshot,对比这个 2 个 snapshot 发现有大量的 closure (新增 100W+),都是 node-scheduled 这个库产生的

服务器用的是双核 4G,这个服务器上只允许了这个一个 node 进程,在运行 4 小时左右 loop delay 已经达到 20ms+了,当前进程 CPU 快超过 80%了,运行时间越长 loop delay 能达到上百,进程 CPU 超过 100%

1.上述定时器我改用 settimeout 和 setinterval 会不会好一些? 2.对于只跑一个 node 进程来说 买多核有用吗?

node:8.4,node-scheduled:1.2.4

7195 次点击
所在节点    Node.js
28 条回复
imherer
2017-12-06 14:24:51 +08:00
@fds 旧的 task 没有 cancel,因为我这里的 task 都是只执行一次的,即在某个时间点执行一次,执行之后才会有新的 task 产生,我产生新的 task 是直接把新旧 taks 覆盖掉。不知道这里有没有问题。 因为都是只执行一次而且都是已经执行过了,task 再 cancel 已经没意义了吧?
chairuosen
2017-12-06 14:31:39 +08:00
@imherer 也许这就是问题,你知道只执行一次,但是 node 不知道呀,闭包一直留着呢
imherer
2017-12-06 14:35:22 +08:00
@chairuosen 听你这么一说好像有点道理。 也没深入了解过这个库,我以为这种只执行一次的任务是不需要 cancel 的,我先把这部分修改了
fds
2017-12-06 14:38:33 +08:00
@imherer 建议你看下源码,只有调用 cancel,才会从 scheduledJobs 这个字典里删除,否则就一直缓存在里面了。

这个设计勉强也可以理解,因为这个库就主要是为了那些会重复执行的 task 设计的。当然在新语法下,这个 scheduledJobs 应该用 WeakMap 比较好。

总之,你那需求应该用 setTimeout ……当然我觉得更好的做法是与客户端同步服务器时间,然后是直接告知在某某时间点某某道具开始有效,不必用定时器。生效前客户端就消耗了道具应该视为无效。正确消耗了,通知下一个时间点即可。
imherer
2017-12-06 14:45:30 +08:00
@fds 嗯。让客户端来做倒计时服务端验证应该是最好的。 我看了下 snapshot 确实是好多 scheduledJob 都在_cache 里,应该就是没 cancel 掉。 我先本地测试下,thanks。
123s
2017-12-06 15:35:49 +08:00
node-scheduled 以前用来做定时爬虫,跑一段时间就挂,我就猜是它
123s
2017-12-06 15:40:52 +08:00
好吧,看错了,不是这个
jyf
2017-12-06 15:46:43 +08:00
可以考虑用 libev 定制个这种外部服务 比自己维护好点 到点了来触发下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/412402

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX