Django 模型中的 Long 运行 后台线程
Long running background thread in Django model
我对 Python 和 Django 还很陌生,如果有更好的方法,请告诉我。我想要做的是让每个设备(从 models.Model 继承)启动一个长 运行ning 后台线程,不断检查该设备的运行状况。然而,当我 运行 我的代码时,它似乎不像守护进程那样执行,因为服务器缓慢并且不断超时。这个后台线程将(在大多数情况下)运行 程序的生命周期。
下面是我的代码的简化版本:
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)
这似乎是对线程的一种非常简单的使用,但每次我搜索解决方案时,建议的方法是使用芹菜,这对我来说似乎有点过分了。有没有办法让它工作而不需要芹菜之类的东西?
当您开始使用开发环境时,设备数量可能非常少。因此,当您进行测试时,线程数可能是两位数。
但随着设备数量的增加,即使代码可以正常工作,这个线程问题也会很快变得难以为继。因此,使用带有 celery beat 的芹菜是更好的方法。
还要考虑到您是 Django 和 Python 的新手,尝试在此基础上掌握线程会增加更多的复杂性。最后使用 celery 会更简单、更整洁。
正如@knbk 在评论中提到的,"Every time you query for devices, a new thread will be created for each device that is returned"。这是我原来忽略的。
但是,我能够使用作为 Django 应用程序启动的单个后台线程解决我的问题。这是一种比添加第 3 方库(如 Celery)更简单的方法。
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)
我对 Python 和 Django 还很陌生,如果有更好的方法,请告诉我。我想要做的是让每个设备(从 models.Model 继承)启动一个长 运行ning 后台线程,不断检查该设备的运行状况。然而,当我 运行 我的代码时,它似乎不像守护进程那样执行,因为服务器缓慢并且不断超时。这个后台线程将(在大多数情况下)运行 程序的生命周期。
下面是我的代码的简化版本:
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)
这似乎是对线程的一种非常简单的使用,但每次我搜索解决方案时,建议的方法是使用芹菜,这对我来说似乎有点过分了。有没有办法让它工作而不需要芹菜之类的东西?
当您开始使用开发环境时,设备数量可能非常少。因此,当您进行测试时,线程数可能是两位数。
但随着设备数量的增加,即使代码可以正常工作,这个线程问题也会很快变得难以为继。因此,使用带有 celery beat 的芹菜是更好的方法。
还要考虑到您是 Django 和 Python 的新手,尝试在此基础上掌握线程会增加更多的复杂性。最后使用 celery 会更简单、更整洁。
正如@knbk 在评论中提到的,"Every time you query for devices, a new thread will be created for each device that is returned"。这是我原来忽略的。
但是,我能够使用作为 Django 应用程序启动的单个后台线程解决我的问题。这是一种比添加第 3 方库(如 Celery)更简单的方法。
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)