Вопрос или проблема
Моя конфигурация: Intel® Core™ i7-2600 и 16 ГБ оперативной памяти DDR3
varnish+nginx+php-fpm+apc для не очень загруженного блога на WordPress с W3 Total Cache и CDN
Моя проблема в том, что после 55 запросов в секунду согласно blitz.io varnish начинает выдавать таймауты. Использование процессора в это время составляет едва 1%. Свободная память постоянно остается более 10 ГБ.
Я пытался проводить нагрузочное тестирование php-fpm напрямую с результатом 150 запросов/с без каких-либо таймаутов. Но после этого использование процессора достигает 100%, и он перестает отвечать.
Можете помочь мне оптимизировать его для обработки большего количества запросов?
Насколько я понимаю, nginx здесь ни при чем, поэтому я не включил его конфигурацию.
Конфигурация php-fpm
listen = /tmp/php5-fpm.sock
listen.allowed_clients = 127.0.0.1
user = nginx
group = nginx
pm = dynamic
pm.max_children = 150
pm.start_servers = 7
pm.min_spare_servers = 2
pm.max_spare_servers = 15
pm.max_requests = 500
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
apc
extension = apc.so
apc.enabled=1
apc.shm_size=512MB
apc.num_files_hint=0
apc.user_entries_hint=0
apc.ttl=7200
apc.use_request_time=1
apc.user_ttl=7200
apc.gc_ttl=3600
apc.cache_by_default=1
apc.filters
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.file_update_protection=2
apc.enable_cli=0
apc.max_file_size=1M
apc.stat=1
apc.stat_ctime=0
apc.canonicalize=0
apc.write_lock=1
apc.report_autofilter=0
apc.rfc1867=0
apc.rfc1867_prefix =upload_
apc.rfc1867_name=APC_UPLOAD_PROGRESS
apc.rfc1867_freq=0
apc.rfc1867_ttl=3600
apc.include_once_override=0
apc.lazy_classes=0
apc.lazy_functions=0
apc.coredump_unmap=0
apc.file_md5=0
apc.preload_path
Varnish VCL
backend default {
.host = "127.0.0.1";
.port = "8080";
.connect_timeout = 6s;
.first_byte_timeout = 6s;
.between_bytes_timeout = 60s;
}
acl purgehosts {
"localhost";
"127.0.0.1";
}
# Вызывается после того, как документ был успешно получен от объединенного сервера.
sub vcl_fetch {
# Раскомментируйте, чтобы сделать время жизни кэша по умолчанию 5 минут, удобно
# но это может кэшировать устаревшие страницы, если не очищать. (TODO)
# По умолчанию Varnish будет использовать заголовки, отправляемые ему Apache (объединенным сервером)
# чтобы определить правильное TTL.
# WP Super Cache отправляет TTL 3 секунды, установленный в wp-content/cache/.htaccess
set beresp.ttl = 24h;
# Убираем куки для статических файлов и устанавливаем длительное время истечения кэша.
if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$") {
unset beresp.http.set-cookie;
set beresp.ttl = 24h;
}
# Если найдены куки WordPress, то страница не подлежит кэшированию.
if (req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)") {
# set beresp.cacheable = false;#версии меньше 3
#beresp.ttl>0 подлежит кэшированию, так что 0 не будет закэшировано
set beresp.ttl = 0s;
} else {
#set beresp.cacheable = true;
set beresp.ttl=24h;#кэш на 24 часа
}
# Varnish определил, что объект не подлежит кэшированию
#если ttl не > 0 секунд, то он подлежит кэшированию
if (!beresp.ttl > 0s) {
# set beresp.http.X-Cacheable = "NO:Not Cacheable";
} else if ( req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)" ) {
# Вы не хотите кэшировать контент для вошедших пользователей
set beresp.http.X-Cacheable = "NO:Got Session";
return(hit_for_pass); #ранее просто pass, но изменено в версии 3+
} else if ( beresp.http.Cache-Control ~ "private") {
# Вы уважаете заголовок Cache-Control=private от объединенного сервера
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
return(hit_for_pass);
} else if ( beresp.ttl < 1s ) {
# Вы искусственно продлеваете срок жизни объекта
set beresp.ttl = 300s;
set beresp.grace = 300s;
set beresp.http.X-Cacheable = "YES:Forced";
} else {
# Varnish определил, что объект подлежит кэшированию
set beresp.http.X-Cacheable = "YES";
if (beresp.status == 404 || beresp.status >= 500) {
set beresp.ttl = 0s;
}
# Доставляем контент
return(deliver);
}
sub vcl_hash {
# Каждая закэшированная страница должна быть идентифицирована по ключу, который ее разблокирует.
# Добавьте браузерный куки только если найден куки WordPress.
if ( req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)" ) {
#set req.hash += req.http.Cookie;
hash_data(req.http.Cookie);
}
}
# vcl_recv вызывается каждый раз, когда получен запрос
sub vcl_recv {
# удаляем ?ver=xxxxx строки из URL, чтобы css и js файлы кэшировались.
# Будьте осторожны при обновлении WordPress, необходимо перезапустить Varnish или очистить кэш.
set req.url = regsub(req.url, "\?ver=.*$", "");
# Убираем "replytocom" из запросов, чтобы улучшить кэширование.
set req.url = regsub(req.url, "\?replytocom=.*$", "");
remove req.http.X-Forwarded-For;
set req.http.X-Forwarded-For = client.ip;
# Исключите этот сайт, потому что он не работает, если закэширован
if ( req.http.host == "sr.ituts.gr" ) {
return( pass );
}
# Обслуживайте объекты до 2 минут после истечения их срока, если объединенный сервер медленно отвечает.
set req.grace = 120s;
# Убираем куки для статических файлов:
if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$") {
unset req.http.Cookie;
return(lookup);
}
# Удаляем has_js и куки Google Analytics __*.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
# Удаляем префикс ";", если он присутствует.
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
# Удаляем пустые куки.
if (req.http.Cookie ~ "^\s*$") {
unset req.http.Cookie;
}
if (req.request == "PURGE") {
if (!client.ip ~ purgehosts) {
error 405 "Не разрешено.";
}
#в предыдущей версии ban() был purge()
ban("req.url ~ " + req.url + " && req.http.host == " + req.http.host);
error 200 "Очищено.";
}
# Пропускаем все, кроме GET и HEAD напрямую.
if (req.request != "GET" && req.request != "HEAD") {
return( pass );
} /* Мы по умолчанию обрабатываем только GET и HEAD */
# убираем куки для комментариев, чтобы улучшить кэширование.
set req.http.cookie = regsub(req.http.cookie, "1231111111111111122222222333333=[^;]+(; )?", "");
# никогда не кэшировать страницы администратора, страницу состояния сервера или вашу ленту? вы можете захотеть .. я не
if (req.request == "GET" && (req.url ~ "(wp-admin|bb-admin|server-status|feed)")) {
return(pipe);
}
# не кэшировать аутентифицированные сессии
if (req.http.Cookie && req.http.Cookie ~ "(wordpress_|PHPSESSID)") {
return(lookup);
}
# не кэшировать ajax запросы
if(req.http.X-Requested-With == "XMLHttpRequest" || req.url ~ "nocache" || req.url ~
"(control.php|wp-comments-post.php|wp-login.php|bb-login.php|bb-reset-password.php|register.php)") {
return (pass);
}
return( lookup );
}
Опции демона Varnish
DAEMON_OPTS="-a :80 \
-T 127.0.0.1:6082 \
-f /etc/varnish/ituts.vcl \
-u varnish -g varnish \
-S /etc/varnish/secret \
-p thread_pool_add_delay=2 \
-p thread_pools=8 \
-p thread_pool_min=100 \
-p thread_pool_max=1000 \
-p session_linger=50 \
-p session_max=150000 \
-p sess_workspace=262144 \
-s malloc,5G"
Я не уверен, с чего начать. Должен ли я начать с оптимизации php-fpm, а затем перейти к varnish? Или php-fpm уже на пределе, так что мне следует начать искать проблему в varnish?
В конфигурации: Опции демона Varnish
После изменения специальных параметров и по умолчанию. Я вижу, что они одинаковые
Я где-то читал, что вы можете рассчитать свой max_children
на основе того, сколько памяти вы выделяете для apc.shm_size
. Мне кажется, что у вас слишком большое значение.
Введите “free” и разделите свою память на количество памяти, выделяемой для APC. Это будет ваш max_children
.
Я предлагаю начать с низкого значения для apc.shm_size
, скажем, 32 МБ. Настраивайте оттуда.
Ответ или решение
Для оптимизации php-fpm и Varnish для вашего мощного сервера с процессором Intel Core i7-2600 и 16 ГБ ОЗУ, нужно обратить внимание на несколько ключевых аспектов. Ваш текущий стек включает Varnish, nginx, php-fpm и APC, и, судя по всему, вы сталкиваетесь с проблемами при увеличении нагрузки на 55 запросов в секунду. Разберем возможные причины торможений и методы их устранения.
Общий анализ
-
Производительность CPU и RAM:
- Вы упомянули, что загрузка CPU остается на уровне 1% при 55 запросах в секунду, но при тестировании php-fpm напрямую она достигает 100%. Это говорит о том, что либо php-fpm, либо Varnish или их конфигурация не оптимизированы для многопоточного выполнения.
- Свободная память (10 ГБ) указывает на то, что у вас достаточно ресурсов, но вам нужно убедиться, что их использование эффективно.
-
Конфигурация php-fpm:
- Ваша текущая конфигурация
pm.max_children = 150
может быть слишком высокой, если учесть доступное количество памяти в сочетании с настройками APC. - Учитывая выделенные 512 МБ на
apc.shm_size
, мы можем сделать следующие расчеты. Если максимальное количество php процессов будет 150 и каждый процесс потребляет (допустим) 50 МБ, то всего вам необходимо 7.5 ГБ ОЗУ. Это не учитывает другие процессы на сервере и может привести к истощению памяти, что, в свою очередь, вызывает тайм-ауты.
- Ваша текущая конфигурация
Рекомендации по оптимизации
1. Настройки php-fpm
- Уменьшите
pm.max_children
до 75, начните с 25, затем увеличивайте в зависимости от нагрузки и доступной памяти. - Уменьшите
apc.shm_size
до 32 МБ и смотрите на изменения производительности. Затем плавно увеличивайте, если это необходимо. Это даст больше памяти для php-fpm процессов. - Рассмотрите возможность изменения
pm
сdynamic
наondemand
, что может снизить использование памяти, активируя процессы php-fpm только по необходимости.
Пример конфигурации php-fpm
listen = /tmp/php5-fpm.sock
listen.allowed_clients = 127.0.0.1
user = nginx
group = nginx
pm = ondemand
pm.max_children = 75
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.process_idle_timeout = 10s
pm.max_requests = 500
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
2. Лучшие практики для APC
- Проверьте
apc.filters
и добавьте фильтры по необходимости. Например, если какие-то файлы не обязательны для кеширования, настройте их исключение. - Увеличьте
apc.num_files_hint
на количество файлов, которые вы ожидаете кешировать для более быстрой работы.
3. Конфигурация Varnish
Убедитесь, что Varnish правильно настроен для работы с nginx:
- Увеличьте значения
connect_timeout
,first_byte_timeout
иbetween_bytes_timeout
, чтобы учесть возможные задержки со стороны php-fpm.
Пример конфигурации Varnish
backend default {
.host = "127.0.0.1";
.port = "8080";
.connect_timeout = 10s;
.first_byte_timeout = 10s;
.between_bytes_timeout = 10s;
}
Тестирование и мониторинг
- Используйте инструменты мониторинга, такие как
top
,htop
илиnload
, чтобы отслеживать работу вашего сервера в реальном времени при увеличении нагрузки. - Проведите нагрузочное тестирование с помощью Apache Bench или Siege для определения пределов производительности при разных конфигурациях.
Заключение
После внесения указанных изменений, проводите регулярное тестирование производительности и корректируйте конфигурации по мере необходимости. Следует обратить внимание на баланс ресурсов и динамическое распределение нагрузки, чтобы избежать узких мест. С течением времени и с настройками, вам удастся оптимизировать ваш стек для работы с высокой нагрузкой.