Планировщик времени асинхронного мониторинга laravel

PHP

Что такое планировщик времени

Laravel предоставляет функцию заказа запланированной задачи по умолчанию.Под другими фреймворками php, без этой запланированной задачи, как мы запускаем некоторые асинхронные скрипты?Мы можем полагаться только на crontab, предоставленный нашей системой, что приводит нас каждый раз к новым запланированных задач в версии выпуска, вы должны перейти на сервер, чтобы изменить код crontab, чтобы получить и обновить эту конфигурацию.

Команда выполнения выполняется php artisan schedule:run.Где она должна выполняться?Да, этот вызов все еще должен выполняться нашим crontab, но его нужно настроить только один раз, а все последующие запланированные задачи контролируются нашим бизнесом код.

Сцены

У нас есть запланированная задача, которая импортирует данные

//每分钟导入库数据
$schedule->command(self::SIGNATURE)->withoutOverlapping()->everyMinute()->runInBackground();
  1. Здесь лучше всего использовать runInBackground() для долгого импорта, что означает асинхронное выполнение, по сути это добавление символа & в конец скрипта оболочки, который полностью зависит от системы в Linux.
  2. Здесь withOverlapping() используется, чтобы указать, что одновременно может выполняться только одна задача.Основная логика реализована с помощью эксклюзивной блокировки, которая зависит от драйвера нашего кеша.Я использую здесь redis, который непосредственно предоставляется redis по мере истечения срока действия блокировки.Для этого истекает срок действия ключа.

проблема появляется

Эта задача идеально подходит для обычных условий, потому что одновременно выполняется только один запуск, и его достаточно запустить, но появляется сцена.

Через день после того, как наши одноклассники qa только что развернули окружение, наш сервер молча импортировал библиотеку, потому что с помощью WithoutOverlapping($expire_at=1440) в это время в redis была сгенерирована блокировка, параметром по умолчанию является истечение срока действия блокировки. время по умолчанию — один день, а затем, поскольку нашей среде докеров необходимо изменить параметры, а затем перезапустить службу внутреннего сервера, наш перезапуск также является относительно насильственным, то есть напрямую отправляет сигнал уничтожения, вызывая запуск всех процессов. в нем убиться моментально, а в это время мы Блокировка redis еще существует, а это минут 1440. При перезапуске сервера мы обнаруживаем, что блокировка существовала всегда, и нет возможности проводить последующие операции Мы можем только ждать.

решить

  1. Потом могу уменьшить время блокировки.Изначальное один день,я поменял на 30 минут,без проблем,мы так же делали в начале первой версии плана,может и официал.
  2. Позже мы подумали над тем, можно ли реализовать программу мониторинга, которая бы следила за истечением сразу после выхода из процесса, чтобы не было необходимости устанавливать фиксированное время.Это, конечно, идеальное состояние всех разработчиков программного обеспечения: если вы хотите чтобы открыть, можно открыть, а я вешаю.Блокировка тоже снимается, нормальная или нет.

решение

проиллюстрировать:

  1. Когда эта команда запустится, получите pid процесса, а затем разветвите дочерний процесс, вы можете передать pid дочернему процессу.
  2. Дочерний процесс выполняет проверку каждые 10 секунд, чтобы узнать, соответствует ли идентификатор родительского процесса входящему pid. Вот точка знаний. Если родительский процесс завершается ненормально, дочерний процесс будет процессом инициализации (pid = 1) до он завершает работу, то это процесс-сирота.
  3. В то же время дочерний процесс будет изменять время истечения блокировки redis каждый раз, когда он обнаруживает активность.Если интервал обнаружения равен 10 с, то наша настройка времени истечения составляет 14 с, что немного более избыточно.

Код

Реализация кода всегда такая бледная, вот расширение laravel для этого, преимущество в том, что оно будет завершено, не затрагивая какой-либо код нашего основного тела, и наш laravel можно обновить по желанию.

адрес гитхаба:GitHub.com/this 78727258…

Адрес композитора:хлопать в ладоши gist.org/packages/ затем…

Суммировать

  1. Общая реализация не использует такие команды, как ps grep, для оценки существования процесса, потому что наша среда докеров не обязательно поддерживает эти команды, но для сравнения используются простые pid и parent_id.
  2. Метод крюка Larave's используется в начале и конце команды, мы можем слушать под слушателем.
public function subscribe($events)
    {
        $events->listen(
            [
                CommandStarting::class, // 命令开始的时候
            ],
            __CLASS__ . '@handle'
        );
    }
  1. Общий код расширен на основе laravel и не повлияет на операцию обновления laravel.