2017-07-10 44 views
1

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

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

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) 

这似乎是一个很简单的使用线程的,但我每次寻求解决方案时,建议的方法是使用芹菜这似乎是矫枉过正我。有没有办法让这个工作,而不需要像西芹?

+0

表中会出现多少个设备条目?什么是您需要检查设备状态的时间间隔? –

+0

如果这是我的应用程序,我会cron [自定义管理命令](https://docs.djangoproject.com/en/1.11/howto/custom-management-commands/),或者我将在[芹菜]( http://www.celeryproject.org/) – danihp

+0

无论何时初始化一个新的'Device'实例,您都会开始一个新的后台线程。每次查询设备时,都会为每个返回的设备创建一个新线程。这可以快速创建数十个(如果不是数百个)线程,这会占用您的服务器并从服务于网页的线程中提取资源。我会说只是使用芹菜,并正确地做。 – knbk

回答

0

@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) 
0

当您在开发环境中开始使用时,设备数量可能相当低。所以当你测试一下时,线程的数量可能是两位数。

但是这个线程问题很快就会变得站不住脚,即使你有代码工作,也会增加设备的数量。所以使用celery beat的芹菜是更好的方法。

另外考虑到你是Django和Python的新手,试图掌握最重要的线程会增加更多的复杂性。使用芹菜这将是一个更简单和最后整洁。

相关问题