четверг, 22 января 2015 г.

Что будет если в нескольких вкладках браузера запустить один и тот же скрипт?

Наткнулся на интересный момент, который связан с работой браузеров. Имеется PHP скрипт у которого есть защита от одновременного запуска нескольких копий через flock()

<?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 в других вкладках натыкаются на незавершенную операцию и ожидают - ведь возможно удастся выдать результат, используя кеш. Когда отрабатывает первый запрос, браузер видит ответ сервера, запрещающий кеширование результата и запускает второй запрос. Таким образом все запросы выполняются последовательно, успешно получая блокировку. Завтра нужно будет проверить, действительно ли только один запрос выполняется сервером одновременно.

Комментариев нет:

Отправить комментарий