<?php $fp = fopen($_SERVER['SCRIPT_FILENAME'], 'r'); if (flock($fp, LOCK_EX | LOCK_NB)) { echo 'Job started' . PHP_EOL; sleep(10); flock($fp, LOCK_UN); } else { echo 'Another job already running' . PHP_EOL; } fclose($fp); ?>
Такой код обеспечивает надежную блокировку от одновременного запуска нескольких копий задания на уровне процесса. Но при тестировании оказалось, что если этот скрипт запустить в нескольких вкладках одного браузера, то вместо быстрого завершения с выводом 'Another job already running' вкладки последовательно срабатывали, выводя 'Job started'. Но этого быть не должно, ведь используется неблокирующий вызов flock()!
Для проверки запустил несколько запросов, через wget
$ for i in $(seq 1 5); do wget -q -O- http://localhost/flock.php & done [1] 30876 [2] 30877 [3] 30878 [4] 30879 [5] 30880 $ Another job already running Another job already running Another job already running Another job already running Job started
Сейчас все верно - сначала в фоне запустился первый скрипт, получил блокировку и уснул, имитируя бурную деятельность. Четыре остальных запуска завершились сразу, не получив блокировку.
Я не знаю точно, почему так происходит, но возможно дело в кеше браузера. Когда URL запрашивается в первый раз он помечается в кеше как pending, пока не будет ответа от сервера. Последующие запросы того же URL в других вкладках натыкаются на незавершенную операцию и ожидают - ведь возможно удастся выдать результат, используя кеш. Когда отрабатывает первый запрос, браузер видит ответ сервера, запрещающий кеширование результата и запускает второй запрос. Таким образом все запросы выполняются последовательно, успешно получая блокировку. Завтра нужно будет проверить, действительно ли только один запрос выполняется сервером одновременно.
Комментариев нет:
Отправить комментарий