Комментарии 20
Спасибо, полезная информация.
Phpstorm не слышал на удивление.
Слышали ли вы про PHP-функции realpath_cache_get() и realpath_cache_size()?
Phpstorm не слышал на удивление.
github.com/JetBrains/phpstorm-stubs добавьте :)
Переводчику: не забывайте переводить слово «деплой».
Содержание статьи — еще одна палка в сторону PHP.
m1el@m1el:/tmp$ cat symlink.php
<?php
chdir("/tmp");
system("rm lnk; ln -s dir1 lnk");
print(realpath("lnk/file.txt") . "\n");
system("rm lnk; ln -s dir2 lnk");
print(realpath("lnk/file.txt") . "\n");
m1el@m1el:/tmp$ php symlink.php
/tmp/dir1/file.txt
/tmp/dir1/file.txt
Если это перевод, то где ссылка на оригинал?
(или я немного ослеп..)
(или я немного ослеп..)
Сколько миллионов раз в секунду вы дергаете realpath() и зачем?
Да взять хотя бы автолоадеры… Я их пишу через realpath как раз из-за керишованного резолвинга путей.
Все намного проще. Сценарий получения ошибки такой:
Веб-сервер смотрит в папку
Структура папки www следующая:
Новая версия кода выкладыватется в отдельную папку, ссылка htdocs переключается на новую версию.
В коде в новой версии добавляется инклюд (новая библиотека, класс, служебный файл, любая сущность на диске). PHP разрешил путь до
Итого: версию выложили, переключили ссылки, и около 2 минут сыпятся фаталы
Хуже, если старая версия удалена — фаталы будут сыпаться гуще. А в случае, когда необходимо синхронное переключение, могут возникнуть неведомые ошибки, которые никогда больше не воспроизведутся и могут принести сильнуюпопа головную боль.
Дергать миллион раз ничего не нужно, достаточно использовать Composer Autoload :)
Веб-сервер смотрит в папку
/var/www/htdocs
Структура папки www следующая:
$ ls -al /var/www
htdocs -> version-71928
version-59189
version-71928
Новая версия кода выкладыватется в отдельную папку, ссылка htdocs переключается на новую версию.
В коде в новой версии добавляется инклюд (новая библиотека, класс, служебный файл, любая сущность на диске). PHP разрешил путь до
/var/www/htdocs
в виде /var/www/version-71928
и закешировал. После переключения ссылки старый кэш будет актуален вплоть до 2 минут (по умолчанию, в зависимости от realpath_cache_ttl) и все новые файлы будут искаться в прошлой версии. Итого: версию выложили, переключили ссылки, и около 2 минут сыпятся фаталы
Unknown: Failed opening required '/var/www/htdocs/include.php'
Хуже, если старая версия удалена — фаталы будут сыпаться гуще. А в случае, когда необходимо синхронное переключение, могут возникнуть неведомые ошибки, которые никогда больше не воспроизведутся и могут принести сильную
Дергать миллион раз ничего не нужно, достаточно использовать Composer Autoload :)
Достаточно выкладывать билды в новый каталог вида /path/to/application/$revisionNumber и обновлять конфигурацию веб-сервера.
Это решает и множество других проблем — атомарность переключения (не получится, что в какой-то момент будут использованы два файла от разных версий), возможность отката на предыдущий билд.
Это решает и множество других проблем — атомарность переключения (не получится, что в какой-то момент будут использованы два файла от разных версий), возможность отката на предыдущий билд.
Атомарности переключения вообще очень сложно добиться. Есть два варианта:
1) Разорвать текущие соединения (restart), при этом будет атомарность, но клиенты получат ошибки
2) Нормально завершить текущие соединения (reload), в этом случае атомарности не будет — параллельно будут работать и старые, и новые, но клиенты ошибок не получат.
В зависимости от требований, выбирается подходящий вариант.
Что касается кофигурации, решение со ссылкой решает одну очень важную проблему — права доступа. Для изменения ссылки не требуется привелегий, достаточно прав на запись в папку с проектом. Для перезапуска же сервера требуется привелегированный доступ (читай: root), да и возможности ошибиться там намного больше. Возможность отката сохраняется.
У php-fpm есть проблемы с reload: bugs.php.net/bug.php?id=60961, поэтому в любом случае приходится искать решение уровнем выше.
Чтобы сохранить окружение целым и не давать рутовых прав CI, для нас оптимальным вариантом стало отключать ноду на балансировщике, ждать завершения процессов, обновляться, включать ноду обратно.
1) Разорвать текущие соединения (restart), при этом будет атомарность, но клиенты получат ошибки
2) Нормально завершить текущие соединения (reload), в этом случае атомарности не будет — параллельно будут работать и старые, и новые, но клиенты ошибок не получат.
В зависимости от требований, выбирается подходящий вариант.
Что касается кофигурации, решение со ссылкой решает одну очень важную проблему — права доступа. Для изменения ссылки не требуется привелегий, достаточно прав на запись в папку с проектом. Для перезапуска же сервера требуется привелегированный доступ (читай: root), да и возможности ошибиться там намного больше. Возможность отката сохраняется.
У php-fpm есть проблемы с reload: bugs.php.net/bug.php?id=60961, поэтому в любом случае приходится искать решение уровнем выше.
Чтобы сохранить окружение целым и не давать рутовых прав CI, для нас оптимальным вариантом стало отключать ноду на балансировщике, ждать завершения процессов, обновляться, включать ноду обратно.
Зачем рута?
# grep nginx /etc/sudoers
%wwwctl ALL = NOPASSWD: /usr/sbin/service nginx configtest
%wwwctl ALL = NOPASSWD: /usr/sbin/service nginx reload
Проблему с релоадом знаю, да — потому без особых причин его стараюсь просто не делать. При смене пути он и не требуется.
# grep nginx /etc/sudoers
%wwwctl ALL = NOPASSWD: /usr/sbin/service nginx configtest
%wwwctl ALL = NOPASSWD: /usr/sbin/service nginx reload
Проблему с релоадом знаю, да — потому без особых причин его стараюсь просто не делать. При смене пути он и не требуется.
Проблема с релоадом решается, например, корректной конфигурацией nginx-а (т.е. уровнем выше, как вы и написали):
В этом случае переключение атомарное, т.к. php-fpm работает уже с настоящим путем, а не ссылкой. И релоад вообще делать не надо.
Впрочем, если при этом надо БД обновлять, тут уже вариантов нет =)
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
В этом случае переключение атомарное, т.к. php-fpm работает уже с настоящим путем, а не ссылкой. И релоад вообще делать не надо.
Впрочем, если при этом надо БД обновлять, тут уже вариантов нет =)
А что касаемо TTL устаревания, есть какие-то рекомендательные значения?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
PHP и realpath_cache