Оптимизируйте php-fpm и varnish для мощного сервера

Вопрос или проблема

Моя конфигурация: 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?

Ответ или решение

Для оптимизации php-fpm и Varnish для вашего мощного сервера с процессором Intel Core i7-2600 и 16 ГБ ОЗУ, нужно обратить внимание на несколько ключевых аспектов. Ваш текущий стек включает Varnish, nginx, php-fpm и APC, и, судя по всему, вы сталкиваетесь с проблемами при увеличении нагрузки на 55 запросов в секунду. Разберем возможные причины торможений и методы их устранения.

Общий анализ

  1. Производительность CPU и RAM:

    • Вы упомянули, что загрузка CPU остается на уровне 1% при 55 запросах в секунду, но при тестировании php-fpm напрямую она достигает 100%. Это говорит о том, что либо php-fpm, либо Varnish или их конфигурация не оптимизированы для многопоточного выполнения.
    • Свободная память (10 ГБ) указывает на то, что у вас достаточно ресурсов, но вам нужно убедиться, что их использование эффективно.
  2. Конфигурация 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 для определения пределов производительности при разных конфигурациях.

Заключение

После внесения указанных изменений, проводите регулярное тестирование производительности и корректируйте конфигурации по мере необходимости. Следует обратить внимание на баланс ресурсов и динамическое распределение нагрузки, чтобы избежать узких мест. С течением времени и с настройками, вам удастся оптимизировать ваш стек для работы с высокой нагрузкой.

Оцените материал
Добавить комментарий

Капча загружается...