当前位置: 首页 > 知识库问答 >
问题:

Django模型中长时间运行的后台线程

华恩
2023-03-14

我对Python和Django相当陌生,所以请让我知道是否有更好的方法来做到这一点。我想做的是拥有每个设备(从模型继承。Model)启动一个长时间运行的后台线程,该线程不断检查该设备的运行状况。然而,当我运行代码时,它似乎不像守护进程那样执行,因为服务器缓慢且不断超时。这个后台线程将(在大多数情况下)运行程序的生命周期。

下面是我代码的简化版本:

class Device(models.Model):
    active = models.BooleanField(default=True)
    is_healthy = models.BooleanField(default=True)
    last_heartbeat = models.DateTimeField(null=True, blank=True)

    def __init__(self, *args, **kwargs):
        super(Device, self).__init__(*args, **kwargs)
        # start daemon thread that polls device's health
        thread = Thread(name='device_health_checker', target=self.health_checker())
        thread.daemon = True
        thread.start()


    def health_checker(self):
        while self.active:
            if self.last_heartbeat is not None:
                time_since_last_heartbeat = timezone.now() - self.last_heartbeat
                self.is_healthy = False if time_since_last_heartbeat.total_seconds() >= 60 else True
                self.save()
                time.sleep(10)

这似乎是线程的一个非常简单的用法,但每次我寻找解决方案时,建议的方法是使用芹菜,这对我来说似乎有些过分了。有没有一种方法可以让它在不需要芹菜之类的东西的情况下发挥作用?

共有2个答案

龙高歌
2023-03-14

当您在开发环境中开始时,设备的数量可能非常少。所以当你测试的时候,线程的数量可能是两位数。

但是,随着设备数量的增加,即使代码能够正常工作,这个线程问题也将很快变得无法解决。所以用芹菜配芹菜酱是更好的方法。

也要考虑到你是新的Django和Python,试图掌握上面的线程会增加更多的复杂度。最后用芹菜做这个会简单得多,也更整洁。

郝冥夜
2023-03-14

正如@knbk在评论中提到的,“每次查询设备时,都会为返回的每个设备创建一个新线程”。这是我最初忽略的事情。

然而,我能够使用作为Django应用程序启动的单个后台线程来解决我的问题。这是一种比添加第三方库(如芹菜)简单得多的方法。

class DeviceApp(AppConfig):
    name = 'device_app'

    def ready(self):
        # start daemon thread that polls device's health
        thread = Thread(name='device_health_checker', target=self.device_health_check)
        thread.daemon = True
        thread.start()

def device_health_check(self):
    while (true):
        for device in Device.objects.get_queryset():
            if device.last_heartbeat is not None:
                time_since_last_heartbeat = timezone.now() - device.last_heartbeat
                device.is_healthy = False if time_since_last_heartbeat.total_seconds() >= 60 else True
                device.save()
        time.sleep(10)
 类似资料:
  • 我有一个在Tomcat7上运行的Spring3.0WebMVC应用程序。在应用程序启动时,我启动一个后台线程来加载内存缓存,其中包含来自数据库的记录。该线程从数据库加载所有数据通常需要一个多小时。在同一个应用程序中,我有一个@Controller注释类,它公开了一个REST接口,客户端可以通过该接口从加载的缓存中获取对象。 我们的要求之一是,在数据加载完成之前发出的任何REST请求都将立即向客户端

  • 我有一个压缩图像的任务,它在图像中使用了许多循环: 我在普通线程中运行此方法,如下所示: 或者在后台工作线程中运行 问题是:这种方法有时会出错,在接收无效输入时会导致无限循环。在这种情况下,它将永远运行,并损害CPU,即使当设备的屏幕关闭时,这会增加设备的温度(如果我使用工作线程,它还会阻止等待队列中的其他任务)。 我想我需要设置一个超时来终止长时间运行的任务。在正常Java线程中实现这一点的最佳

  • 我想实现一个长时间运行的后台计时器,它定期将用户的位置发送到服务器。 为此,我为设置模式,并在应用程序转到后台时调用。对于,我使用方法(不希望使用重大更改,因为我需要高精度的定位)。 但是大约在应用程序进入后台26分钟后,它会停止向服务器发送位置。但是应用程序没有崩溃,所以在我把应用程序带到前台后,它可以恢复计时器。 26分钟来自实验,iOS6.1,苹果5。 这里有一些问题,, > 我不明白为什么

  • 问题内容: 我有一个运行长时间运行的作业的Web服务(大约几个小时)。我正在使用Flask,Gunicorn和nginx进行开发。 我正在考虑做的事情是拥有一条需要很长时间才能完成的路由,调用一个创建线程的函数。然后,该函数将向路径返回一个GUID,并且路径将返回一个URL(使用GUID),用户可以使用该URL来检查进度。我正在将线程设为守护程序(thread.daemon = True),以便如

  • 我正在使用rxjava将一些任务上载到服务器,每当任务启动的片段或活动被销毁时,我都会处理订阅以避免内存泄漏,但我想要的是,即使在片段/活动被销毁后,我也需要继续在后台运行任务,有什么方法可以实现这一点吗? 实例 是否必须始终释放订阅?如果不是,何时使用dispose?