Я пишу серверную систему, которая работает в фоновом режиме. В очень упрощенном виде у него есть свой собственный язык сценариев, что означает, что процесс может быть написан на этом языке для запуска сам по себе, или он может вызывать другой процесс и т. Д. Я конвертирую эту систему из тривиального задания cron PHP в который только один экземпляр разрешен одновременно для набора длительных процессов, управляемых Supervisor.
Имея это в виду, я осознаю, что эти процессы могут быть убиты в любое время, либо мной самим в процессе разработки, либо, возможно, Supervisord в ходе обычной остановки или перезапуска работника. Я хотел бы добавить некоторую правильную обработку сигналов для обеспечения того, чтобы работники убирались за собой, и, при необходимости, регистрировать, где задача была оставлена в прерванном состоянии.
Я разработал, как включить обработку сигналов с помощью тиков и pcntl_signal()
и моя обработка в настоящее время, кажется, работает нормально. Тем не менее, я хотел бы проверить это, чтобы убедиться, что это надежно. Я написал несколько ранних интеграционных тестов, но они не кажутся такими уж солидными, в основном потому, что во время разработки возникали всевозможные странные проблемы, связанные с состоянием гонки, которые было сложно определить.
Я хотел бы получить совет или руководство по отправке сигналов уничтожения в тестах PHPUnit, чтобы повысить уверенность в том, что моя обработка sig надежна. Моя нынешняя стратегия:
system()
команда в тесте PHPUnit. Моя команда похожа на php script.php > $logFile 2>&1 &
то есть перенаправить весь вывод в файл журнала, а затем перенести его в фоновый режим, чтобы тестовый метод мог его отслеживатьusleep
между сканированиямиusleep
между сканированием и выдачей kill <pid>
когда он будет готовusleep
снова, чтобы не забивать базу данныхКонечно, со всеми этими ожиданиями / проверками, это кажется немного странным и вполне готовым к гоночным условиям всех видов. В настоящее время у меня такое ощущение, что тесты будут проваливаться примерно в 2% случаев, но я не смог провалить тест в течение дня или около того. Я планирую провести иммерсионное тестирование, и если я получу какие-либо ошибки, я опубликую это здесь.
Интересно, могу ли я упростить это, попросив тестируемую систему kill
само по себе, что удалит два уровня проверки ожидания (один для ожидания PID, а другой — для ожидания перехода базы данных в правильное состояние перед командой kill)†. Это по-прежнему оставляло бы цикл ожидания-проверки после того, как было выполнено kill, но я все же могу обнаружить, что наличие такой проверки на практике не является проблемой.
Тем не менее, я осознаю, что весь мой подход может быть сорван, и есть лучший подход для такого рода вещей. Есть идеи? В настоящее время я думаю просто увеличить время ожидания на случай, если PHPUnit вводит какие-то странные задержки. Я также посмотрю, смогу ли я получить случай неудачи для проверки журналов.
† К сожалению, это не сильно упростит ситуацию. Я только что попробовал это на простом тесте интеграции сигнала, который я считаю надежным, и так как system()
немедленно возвращается, он все еще должен ждать цикла, чтобы определить правильную запись журнала, а затем для правильного результата после уничтожения. Однако больше не нужно ждать, пока PID будет записан во временный файл, так что исключен хотя бы один цикл.
Как я упоминал в этом вопросе, первое изменение надежности, которое я попробовал, заключалось в том, чтобы внедрить возможность выполнения рабочих задач. kill
на себя. В моем случае это было встроено в систему, но читатели могут обнаружить, что написание дочернего тестового класса и изменение их конфигурации DI было бы удобным способом сделать это.
Кажется, это значительно улучшило надежность. Первоначально в тестах было несколько циклов ожидания, и тест должен был запустить kill
в нужный момент:
kill
Возможно, проблема была в (2) — если это слишком коротко, то kill
иногда может приходить слишком поздно, и даже если найдено надежное максимальное время ожидания, если процессор находится под неожиданной нагрузкой, он все равно может быть подвержен сбоям.
Теперь я написал быстрый скрипт для многократного запуска тестов PHPUnit, либо для 200 итераций, либо для первого сбоя, в зависимости от того, что наступит раньше. Теперь это проходит 200 итераций, поэтому пока я буду считать, что надежность теста повысилась. Однако я буду обновлять здесь, если это изменится — возможно, запуск тестов с высоким nice
вызовет сбой.
Другие ответы по-прежнему приветствуются.
Других решений пока нет …