php-fpm генерирует большую нагрузку при сбросе opcache, что делает сервер не отвечающим
В последние недели мы столкнулись с негативным явлением при развертывании кода: сервер иногда зависает на несколько минут.
Вот пример нагрузки на сервер, когда это произошло:
Единственный связанный журнал, который я могу найти, от /var/log/php7.2-fpm.log
и иногда (но не всегда) я вижу записи, подобные этой (примечание: это из события, отличного от изображения, показанного выше, тем не менее, происходит то же самое):
[22-Mar-2019 15:33:50] WARNING: [pool api] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 0 idle, and 231 total children
[22-Mar-2019 15:33:52] WARNING: [pool api] server reached pm.max_children setting (250), consider raising it
[22-Mar-2019 15:34:05] WARNING: [pool app] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 47 idle, and 104 total children
Случилось так, что мы сделали развертывание на этом сервере:
git status --porcelain
проверить на наличие модификацийgit pull origin master
обновить файлы- сброс opcache, то есть мы вызываем конечную точку, которая выполняет
opcache_reset()
- очистка файлов локального кэша
После некоторых экспериментов я мог бы уменьшить проблему нагрузок до следующего: opcache_reset()
Когда я выполняю этот вызов (независимо от каких-либо предыдущих или более поздних этапов развертывания, это происходит также изолированно, когда я просто вызываю эту конечную точку), существует вероятность внезапного скачка загрузки системы.
Если это происходит, и нагрузка "слишком высока" (я бы сказал, из опыта> 200 или около того), система перестает отвечать на запросы в течение секунд или минут, в зависимости от того, как долго все это успокаивается.
Технические характеристики:
- ВМ работает на VMWare (не мы сами, у нас есть партнер)
- 4 виртуальных ЦП
- 8 ГБ ОЗУ
- Пространство подкачки 8GB
- Ubuntu 18.04 TS
- nginx 1.14.0 (по умолчанию в Ubuntu)
- PHP 7.2 (через https://launchpad.net/~ondrej/+archive/ubuntu/php)
Конфигурация PHP-FPM:
- Мы используем 6 пулов с разными виртуальными хостами
-
start_servers
непосредственно составляет до 320 php-fpm процессов (также подтверждено с помощьюps auxw|grep -i fpm|grep -v grep |wc -l
) - общее количество
max_children
из всех бассейнов будет около 870
Возможно, итоговые значения здесь слишком высоки, мы хотели справиться с резкими скачками на отдельных виртуальных хостах, которые иногда бывают.
С помощью htop
, система обычно выглядит так:
И, как правило, нагрузка низкая, если у нас нет этого всплеска, который связан со сбросом opcache (о котором я недавно узнал):
Я понимаю, что сброс кеша, и теперь все процессы должны его заново заполнять, потребляет процессор.
Но что я не понимаю
- это только начало происходить недавно, например, может быть, через 1-2 месяца, но только в последние две недели безразличие было заметно
- так бывает не всегда, иногда при сбросе кеша ничего не происходит
Вот вывод opcache_get_status(false)
прямо перед развертыванием:
{
"opcache_enabled": true,
"cache_full": false,
"restart_pending": false,
"restart_in_progress": false,
"memory_usage": {
"used_memory": 67353640,
"free_memory": 66864088,
"wasted_memory": 0,
"current_wasted_percentage": 0
},
"interned_strings_usage": {
"buffer_size": 8388608,
"used_memory": 5215176,
"free_memory": 3173432,
"number_of_strings": 89109
},
"opcache_statistics": {
"num_cached_scripts": 2873,
"num_cached_keys": 5063,
"max_cached_keys": 7963,
"hits": 633581523,
"start_time": 1553172771,
"last_restart_time": 1553248200,
"oom_restarts": 0,
"hash_restarts": 0,
"manual_restarts": 6,
"misses": 9512,
"blacklist_misses": 0,
"blacklist_miss_ratio": 0,
"opcache_hit_rate": 99.9984987161316
}
}
и вот потом:
{
"opcache_enabled": true,
"cache_full": false,
"restart_pending": false,
"restart_in_progress": false,
"memory_usage": {
"used_memory": 57745856,
"free_memory": 76471872,
"wasted_memory": 0,
"current_wasted_percentage": 0
},
"interned_strings_usage": {
"buffer_size": 8388608,
"used_memory": 4337168,
"free_memory": 4051440,
"number_of_strings": 75163
},
"opcache_statistics": {
"num_cached_scripts": 2244,
"num_cached_keys": 3925,
"max_cached_keys": 7963,
"hits": 5893926,
"start_time": 1553172771,
"last_restart_time": 1553265235,
"oom_restarts": 0,
"hash_restarts": 0,
"manual_restarts": 7,
"misses": 4962,
"blacklist_misses": 0,
"blacklist_miss_ratio": 0,
"opcache_hit_rate": 99.91588245106536
}
}
Другие вещи, которые я наблюдал:
- php-fpm довольно скоро перестает отвечать
- nginx все еще работает, если нагрузка не становится ДЕЙСТВИТЕЛЬНО высокой; Я подтвердил это, потому что когда php-fpm в основном недоступен, nginx доставляет сконфигурированную страницу 500
Что на самом деле вызывает эти скачки нагрузки? Как я могу избежать их?
Обновить после принятия ответа:
В основном просто не звонит opcache_reset
и возвращение большинства моих настроек настройки opcache к значениям по умолчанию (т.е. не навязывая их) исправило это.
Этот шаг был частью моего развертывания в течение буквально лет. Я попытался выяснить первоначальную причину и, насколько я мог видеть, это было связано с проблемами развертывания, когда классы ссылались на новый код, который еще не был загружен / обновлен.
Оглядываясь назад, я даже не уверен, что это была настоящая проблема, но мы здесь.
1 ответ
По умолчанию PHP проверяет временную метку файла, чтобы сделать недействительной запись opcache. Это можно отключить, и это единственный сценарий, в котором я могу представить opcache_reset()
будет использоваться. Конечно, это также вызывает проблему, с которой вы столкнулись.
Я рекомендую вернуться к значениям по умолчанию:
opcache.validate_timestamps = 1
opcache.revalidate_freq = 2
opcache.revalidate_path = 0