在设置大量计时器或使用计划任务队列之间寻找解决方案 [英] Looking for a solution between setting lots of timers or using a scheduled task queue

查看:30
本文介绍了在设置大量计时器或使用计划任务队列之间寻找解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个服务(一个游戏),其中一组用户将在一个房间中,在该房间中,它将通过每个用户在特定持续时间(例如 30 秒)内做出选择.如果用户在该时间内没有做出选择,该服务将自动为该用户生成一个选择.如果在持续时间结束之前做出选择,那么下一个用户就开始了,计时器应该重置.

I'm building a service (a game) in which a group of users will be in a room where it will go through each user to make a choice within a certain duration (eg 30s). If the user does not make a choice within that duration, the service will auto generate a choice for that user. If a choice is made before the duration is done, then the next user is up and the timer should reset.

一次可能有数百甚至数千个这样的房间/游戏在进行.

There could be hundreds or even thousands of these rooms/games going on at a time.

我想知道如何实现这一点,我愿意使用 Javascript 或 Python 解决方案.

I'm wondering how to implement this and I'm open to using Javascript or Python solutions.

对于 Python,我想根据需要从线程库中生成尽可能多的计时器,但不确定对性能的影响.所需要做的就是自动生成一个完全不占用资源的选择,并使用 SQLAlchemy 用它更新 postgres.

For Python, I was thinking of spawning as many timers from the threading library as necessary, but unsure of the performance implications. All that needs to be done is auto generate a choice which isn't resource intensive at all, and updating postgres with it with SQLAlchemy.

我也可以使用 celery 并使用相同的方法为我的消息代理提供延迟任务.

I could also use celery and feed my message broker with delayed tasks with the same method.

对于 Javascript,类似于 python 的第一个解决方案,我可以根据需要生成尽可能多的 setTimeouts,但问题是所有超时都在主线程上工作,但就像我说的,任务是不是资源密集型的,我只需要精确到秒.

For Javascript, similar to the python's first solution, i could spawn as many setTimeouts as necessary, but the problem is that all timeouts work on the main thread, but like i said, the tasks are not resource intensive and I only need accuracy to the second.

到目前为止,这些是我所涵盖的唯一解决方案,我想知道什么是最好的并且对其他解决方案也持开放态度.

These are the only solutions I've covered so far, I"m wondering what would be the best and open to other solutions as well.

推荐答案

Node.js 计时器的实现非常高效.它们的实现(在关于它们如何工作的详细文章中进行了描述)可以轻松处理非常大量的计时器.

Node.js timers are very efficiently implemented. Their implementation (described in a detailed article about how they work) can easily handle very large numbers of timers.

它们保存在一个已排序的双向链表中,并且只有下一个触发的计时器才具有与之关联的实际 libuv 系统计时器.当该计时器触发或取消时,列表中的下一个将成为附加到实际 libuv 系统计时器的计时器.当一个新的计时器被设置时,它只是被插入到排序列表中,除非它成为下一个要触发的,否则它只是坐在列表中等待轮到下一个.您可以非常有效地拥有数千个.

They are kept in a doubly linked list that is sorted and only the next timer to fire has an actual libuv system timer associated with it. When that timer fires or is canceled, the next one in the list becomes the one attached to an actual libuv system timer. When a new timer is set, it is just inserted into the sorted list and, unless it becomes the next one to fire, it just sits in the list waiting its turn to be next. You can have thousands of these very efficiently.

这里有一些关于这些计时器如何工作的资源:

Here are a couple resources on how these timers work:

在出现性能问题之前有多少并发 setTimeout?

nodejs内部如何管理定时器

第一篇参考文献包含一堆来自实际 nodejs 代码的注释,这些注释描述了计时器链表系统的工作原理以及它的优化目的.

The first reference contains a bunch of comments from the actual nodejs code that describes how the timer linked list system works and what it's optimized for.

第二篇文章对它的组织方式进行了更高层次的描述.

The second article gives you a little higher level description of how its organized.

还有其他效率,当一个计时器到达列表的开头并触发时,在调用该回调后,node.js 检查列表的前面是否有任何其他现在准备触发的计时器.这将清除与第一个具有相同目标时间"的任何其他计时器,以及在运行这些各种其他回调时到期的任何其他计时器.

There are other efficiencies so that when one timer gets to the start of the list and it fires, then after calling that callback, node.js checks the front of the list for any other timers that are now ready to fire also. This will sweep up any other timers with the same "target time" as the first one and also any others that have come due while these various other callbacks were running.

当你有数千个时,如果那里有很多计时器,那么将一个新的计时器插入到排序链表中的时间会稍微长一些,但是一旦插入,有多少根本就不重要了,因为它只是一直看着下一个要开火的人.因此,即使有数以万计的计时器待处理,坐在那里的过程也只是一个系统计时器(代表下一个要触发的计时器事件)和一堆数据.其他未来计时器的所有数据不会让您坐在那里花费任何费用.

When you have thousands, it will take slightly longer to insert a new timer into the sorted linked list if there are lots of timers in there, but once it is inserted, it hardly matters at all how many there are because it's only ever looking at the next one to fire. So, the process of sitting there with even tens of thousands of timers pending is just one system timer (representing the next timer event to fire) and a bunch of data. All that data for the other future timers isn't costing you anything just sitting there.

对于Javascript,类似于python的第一个解决方案,我可以根据需要产生尽可能多的setTimeouts,但问题是所有超时都在主线程上工作,但就像我说的,任务不是资源密集型的,我只需要精确到秒.

For Javascript, similar to the python's first solution, i could spawn as many setTimeouts as necessary, but the problem is that all timeouts work on the main thread, but like i said, the tasks are not resource intensive and I only need accuracy to the second.

在我看来,nodejs 可以很好地处理您的 setTimeout() 调用数量.如果您在 node.js 中遇到问题,那不是因为计时器的数量,但是如果您要处理的工作多于一个内核可以处理的工作量,则您必须确保将足够的 CPU 用于解决问题.您可以使用 nodejs 集群或使用工作线程或其他 nodejs 进程来帮助处理的工作队列来扩展核心使用.node.js 本身对于任何与 I/O 相关的事情都非常高效,因此只要您不进行大量 CPU 密集型计算,单个 node.js 线程就可以处理大量事件.

It seems to me that nodejs could handle your quantity of setTimeout() calls just fine. If you had an issue in node.js, it wouldn't be because of the number of timers, but you would have to be certain that you apply enough CPU to the problem if you have more work to process than one core can handle. You could expand core usage with nodejs clustering or with a work queue that uses Worker Threads or other nodejs processes to help with the processing. node.js is, by itself, very efficient with anything I/O related so as long as you're not doing major CPU-intensive computation, a single node.js thread can handle a lot of event processing.

请记住,Javascript 计时器不提供准确性保证.如果您使 CPU 停滞不前,某些计时器将比预定时间更晚触发,因为它们不是先发制人的.但是,如果您的任务不是 CPU 密集型的,那么您可能没问题.

Keep in mind that Javascript timers make no accuracy guarantees. If you bog down the CPU, some timers will fire later than scheduled because they aren't pre-emptive. But, if your tasks are not CPU-intensive, then you may be just fine.

这篇关于在设置大量计时器或使用计划任务队列之间寻找解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆