2016-08-16 8 views
1

Я пишу серверную систему, которая работает в фоновом режиме. В очень упрощенных выражениях он имеет собственный язык сценариев, что означает, что процесс может быть написан на этом языке для самостоятельной работы или может вызвать другой процесс и т. Д. Я преобразовываю эту систему из тривиального PHP-задания в который одновременно разрешен только одному экземпляру для набора длительных процессов, управляемых Supervisor.Как сделать надежное интеграционное тестирование обработки сигналов Unix в PHP?

Имея это в виду, я знаю, что эти процессы могут быть убиты в любое время, либо самостоятельно в процессе разработки, либо, возможно, Supervisord в ходе обычной остановки или перезапуска рабочего. Я хотел бы добавить правильную обработку сигналов, чтобы гарантировать, что рабочие убираются за собой, и регистрируют, где задача была оставлена ​​в прерванном состоянии, где это необходимо.

Я разработал, как включить обработку сигналов с использованием тиков и pcntl_signal(), и теперь моя обработка работает нормально. Тем не менее, я бы хотел проверить это, чтобы убедиться, что он надежный. Я написал несколько ранних интеграционных тестов, но они не чувствуют себя такими твердыми, главным образом потому, что во время разработки были всевозможные странные проблемы с гоночным состоянием, которые были сложными, чтобы приколоться.

Мне хотелось бы получить консультацию или руководство о том, как отправлять сигналы об утечке в тестах PHPUnit, чтобы повысить уверенность в том, что моя обработка sig является надежной. Моя нынешняя стратегия:

  • Использование PHPUnit
  • В базовой системе работает он создает файлы различных типов входа, которые могут быть использованы для мониторинга, когда убить задачу
  • Системы ядра запускается с использованием отдельный PHP-скрипт в фоновом режиме с использованием команды system() в тесте PHPUnit. Моя команда похожа на php script.php > $logFile 2>&1 &, т. Е. Перенаправляет весь вывод в файл журнала, а затем нажимает его на задний план, поэтому метод тестирования может отслеживать его.
  • Фоновый сценарий записывает свой ПИД-файл в файл, который будет PID, чтобы убить
  • Это подобран надежно с помощью теста путем сканирования несколько раз для него и usleep ИНГ между запусками
  • тест затем ждет определенного состояния путем сканирования базы данных, usleep ИНГ между запусками, и выдачи kill <pid>, когда он готов
  • Затем он ждет, когда обработчик сигнала начнет запись и запишет новое состояние базы данных, usleep ing снова, чтобы избежать ветчины в базе данных
  • Наконец, он либо определит, находится ли база данных в правильном состоянии, либо после максимального времени задержки, которое проходит/не проходит тест.

Конечно, со всем этим ожиданием/проверкой он чувствует себя немного трофейным и вполне созрел для условий гонки всех видов. Мое нынешнее чувство состоит в том, что тесты будут терпеть неудачу примерно в 2% случаев, но мне не удалось пропустить тест на день или около того. Я планирую провести некоторое погружение, и если я получу какие-то неудачи, я отправлю это здесь.

Непонятно, могу ли я упростить его, попросив тестируемую систему самому kill, которая удалит два уровня проверки ожидания (один для ожидания PID, а другой - для ожидания ввода базы данных в правильное состояние перед командой kill) . Это все равно оставит цикл проверки ожидания после того, как будет выпущено убийство, но я все же могу обнаружить, что проверка этого вопроса на практике не является проблемой.

Тем не менее, я сознаю, что весь мой подход может быть снят с рук, и есть лучший подход к подобным вещам. Есть идеи? В настоящее время я думаю только увеличить время ожидания ожидания, в случае, если PHPUnit вводит какие-либо странные задержки. Я также увижу, могу ли я получить случай сбоя для проверки журналов.


† Ах, к сожалению, это не упростит многое. Я просто попробовал это на простой тест интеграции сигнала, который я считаю надежным, и поскольку исходный код system() немедленно возвращается, ему все равно придется ждать цикла, чтобы идентифицировать правильную запись журнала, а затем для правильного результата после уничтожения. Тем не менее, ему больше не нужно ждать, пока ПИД-код будет записан в временный файл, так что по крайней мере один цикл будет удален.

+0

вероятно, путь к широкому. –

+0

Я вижу, как кто-то может считать его краевым. Тем не менее, мне кажется, что это может показаться слишком широким, потому что, как ни парадоксально, я указал слишком много деталей? Вкратце, он просит, чтобы сделать тесты с использованием сигналов Posix более надежными - я надеюсь, что у кого-то здесь может быть некоторый опыт! Посмотрим... – halfer

ответ

-1

Как я уже упоминал в вопросе, первое изменение надежности, которое я пробовал, заключалось в том, чтобы ввести рабочие задачи для запуска kill. В моем случае это было встроено в систему, но читатели могут обнаружить, что написать класс тестирования для детей и изменить их конфигурацию DI будет удобным способом сделать это.

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

  1. Подождите, PID ребенка, чтобы стать доступным
  2. Дождитесь файлов журнала ребенка чтобы указать, что готов убить
  3. Выдайте kill
  4. Wait для файлов журнала ребенка, чтобы указать обработчик сигнала правильно побежал

проблема может быть в (2) - если это слишком коротко, тогда kill может иногда появляться слишком поздно, и даже если будет найдено надежное максимальное время ожидания, если процессор находится под непредвиденной нагрузкой, он может все еще быть подвержен ошибкам.

Я написал быстрый сценарий для многократного запуска тестов PHPUnit, либо для 200 итераций, либо для первого отказа, в зависимости от того, что наступит раньше. Это теперь проходит 200 итераций, поэтому пока я буду рассматривать надежность теста как поднятую. Однако я буду обновлять здесь, если это изменится - возможно, запуск тестов с высоким nice вызовет сбой.

Другие ответы по-прежнему приветствуются.