我使用celery beat worker来创建使用台球并设置守护进程的新进程,但是守护进程无法正常工作

时间:2018-12-06 11:07:28

标签: celery

台球版3.5.0.5 芹菜4.0.2

复制步骤

我想控制长时间的节拍任务。例如,如果任务未完成,则不运行新进程。

def lock_beat_task(gap_time, flush_time):

    def decorate(func):
        """
       Celery timing task solves the problem that the previous task is executed again when it is not executed.
       problem: Celery is similar to crontab, it will be scheduled regularly, regardless of whether the previous task is executed or not.
       achieve: With the help of the cache, the key is the class name, and each time the schedule is checked, it is checked whether it is executed before, and the key is deleted after the execution.
        :param func:
        :return:
        """

        @wraps(func)
        def wrapper(*args, **kwargs):
            key_name = func.__name__

            logger.info('++++++++{} enter +++++++.'.format(key_name))
            monitor = BeatWokerMonitor(key_name, gap_time, flush_time)
            mo_process = monitor.monitor()
            if mo_process:
                try:
                    logger.info('++++++++{} is running.++++++++'.format(key_name))
                    func(*args, **kwargs)
                    logger.info('{} is graceful end.'.format(key_name))
                except KeyboardInterrupt, e:
                    monitor.logger.info('{} KeyboardInterrupt reset succ'.format(key_name))
                finally:
                    monitor.reset()
                    # mo_process.join()
            else:
                logger.info('{} is running or gap time is not over.'.format(key_name))
            logger.info('{} is end!---.'.format(key_name))
        return wrapper
    return decorate

class BeatWokerMonitor(object):
    """
      Used to maintain/monitor the health status of the beat workerCall beat_worker_shoud_run. 

      If there is no key_name in redis, or the time difference between the current time and key_name is 
      greater than gap_time, create a monitor daemon.

      This daemon is responsible for refreshing the time in key_name at a fixed 
      time.Beat_worker_shoud_run returns true(should run)。 Otherwise return None
    """
    def __init__(self, key_name, gap_time, flush_time):
        """
        秒级时间
        :param key_name:
        :param gap_time:
        :param flush_time:
        """
        self.key_name = key_name
        self.gap_time = gap_time
        self.flush_time = flush_time
        self.db_redis = get_redis_conn(11)

    def start_monitor(self):
        flush_key_process = Process(target=self.flush_redis_key_gap_time, name='{}_monitor'.format(self.key_name), daemon=True)
        flush_key_process.start()

        return flush_key_process

    def monitor(self):
        rd_key_value = self.get_float_rd_key_value()
        if not rd_key_value:
            v = time.time()
            self.db_redis.set(self.key_name, v)
            return self.start_monitor()

        if time.time() - rd_key_value > self.gap_time:
            return self.start_monitor()

    def get_float_rd_key_value(self):
        value = self.db_redis.get(self.key_name)
        if value:
            return float(value)
        else:
            return 0

    def flush_redis_key_gap_time(self):
        old_time = self.get_float_rd_key_value()
        self.logger.info('{} start flush, now is {}'.format(self.key_name, old_time))
        while 1:
            if time.time() - old_time > self.flush_time:
                now = time.time()
                self.db_redis.set(self.key_name, now)
                old_time = now
                self.logger.info('{} monitor flush time {}'.format(self.key_name, now))

            else:
                self.logger.info('{} not flush {} , {}'.format(self.key_name, time.time() - old_time, self.flush_time))

    def reset(self):
        self.db_redis.delete(self.key_name)

和任务代码。您可以编写一些短期任务进行测试。

@app.task
@lock_beat_task(5*60, 10*3)
@send_update_msg("update")
def beat_update_all():
    """

    :return:
    """
    from crontab.update import EAllTicket
    eall = EAllTicket()
    send_task_nums = eall.run()
    return send_task_nums

预期的行为

要在后台运行,因此不能使用多重处理来创建子进程。 改用台球 希望beat_update_all()完成,并且监视进程将自行终止。

实际行为

beat_update_all()已完成,并且监视进程仍在运行。

0 个答案:

没有答案