Назад | Перейти на главную страницу

Выявление узких мест в производительности высокопроизводительного VPS (Apache 2.4 event_mpm / lighttpd / nginx)

У меня довольно высококлассный VPS от vpsblast (их SSD13) - 4 ядра, 16 ГБ ОЗУ, 320 ГБ места на жестком диске SSD на магистрали Интернета 1GigE (практически неоспоримый). Насколько я могу судить, он работает под управлением OpenVZ (используется simfs, существует user_beancounters). База данных находится на другом узле в том же центре обработки данных, и я запускаю php-fpm, но этот тест касается статического изображения размером 9,49 КБ (поскольку php-fpm работает, а приложение чрезвычайно оптимизировано). Все запросы отправляются через https, поэтому я провел тесты http и https, чтобы определить, является ли проблема SSL, но я не уверен, что это проблема. ОС - Ubuntu 12.04 LTS. Я тестировал apache 2.4 (с event_mpm), nginx и lighttpd, и я вижу очень похожую производительность у всех трех, что заставляет меня думать, что проблема не в httpd. В настоящее время я использую apache 2.4 для ответа на эти вопросы. Моя производительность на статическом объекте достигает пика около 400 об / с (запросов в секунду). Это примерно 3,7 Мбит / с, что намного меньше, чем у линии 1GigE.

Итак, первый вопрос: какая производительность должен Я наблюдаю за такой настройкой? В обсуждении в #apache на FreeNode было высказано предположение, что параллелизм 10k не должен быть невозможным, и я должен иметь возможность обслуживать 10k запросов в секунду. Эти ожидания необоснованны?

Следующий вопрос касается выявления узких мест в производительности. Честно говоря, я понятия не имею, с чего начать, так как все выглядит нормально (я добавил скриншоты сверху ниже). Я не делал никаких настроек sysctl, так как они, похоже, в основном контролируются ОС хоста. Я увеличил мягкие и жесткие ограничения в /etc/security/limits.conf:

www-data hard nofile 1048576
www-data soft nofile 1048576
root hard nofile 1048576
root soft nofile 1048576

Мой apache httpd.conf довольно стандартен для 2.4, но вот изменения, которые я внес:

DocumentRoot "/var/www"
<Directory "/var/www">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

<IfModule setenvif_module>
BrowserMatch "MSIE 10.0;" bad_DNT
</IfModule>
<IfModule headers_module>
RequestHeader unset DNT env=bad_DNT
</IfModule>
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
</IfModule>
# Netscape 4.x has some problems…
BrowserMatch ^Mozilla/4 gzip-only-text/html
# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip
# MSIE masquerades as Netscape, but it is fine
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# Don’t compress already-compressed files
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI .(?:avi|mov|mp3|mp4|rm|flv|swf|mp?g)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI .pdf$ no-gzip dont-vary

Header append Vary User-Agent env=!dont-var
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/$1

SSLEngine on
SSLOptions +StrictRequire
SSLProtocol -all +TLSv1 +SSLv3
SSLCipherSuite ALL:!kEDH:!ADH:!SSLv2:!EXPORT56:!EXPORT40:!RC4:!DES:+HIGH:+MEDIUM:+EXP
SSLRandomSeed startup file:/dev/urandom 1024
SSLRandomSeed connect file:/dev/urandom 1024
SSLSessionCache        "shmcb:/usr/local/apache2/logs/ssl_scache(512000)"
SSLSessionCacheTimeout  300
# Masked keys for privacy:)
SSLCertificateFile /usr/local/apache2/conf/xxxxx.crt
SSLCertificateKeyFile /usr/local/apache2/conf/xxxxx.key
SSLVerifyClient none
SSLProxyEngine off
<IfModule mime.c>
    AddType application/x-x509-ca-cert      .crt
    AddType application/x-pkcs7-crl         .crl
</IfModule>
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

ServerTokens Prod
Timeout 300
KeepAlive Off
<IfModule mpm_event_module>
    StartServers          5
    MaxClients         1024
    MinSpareThreads      50
    MaxSpareThreads     150
    ThreadLimit          64
    ThreadsPerChild      64
    MaxRequestsPerChild 20000
    ListenBacklog      4096
</IfModule>

Я не думаю, что это ограничение в конфигурации OpenVZ, так как здесь вывод user_beancounters (ограничения довольно высоки)

Version: 2.5
   uid  resource                     held              maxheld              barrier                limit              failcnt
 1592:  kmemsize                 83776469            113721344           2369781760           2606759936                    0
        lockedpages                  4161                10616               578560               578560                    0
        privvmpages                670407              2743929  9223372036854775807  9223372036854775807                    0
        shmpages                     5770                 7450              1048576              1048576                    0
        dummy                           0                    0                    0                    0                    0
        numproc                       233                 1044                 3560                 3560                    0
        physpages                  157907               290092                    0              4194304                    0
        vmguarpages                     0                    0              4194304  9223372036854775807                    0
        oomguarpages                49397                83795              4194304  9223372036854775807                    0
        numtcpsock                     23                 1317                57330                57330                    0
        numflock                        4                   11                32768                36045                    0
        numpty                          2                    9                  256                  256                    0
        numsiginfo                      1                   30                  256                  256                    0
        tcpsndbuf                  512360             31732952            293529600            440294400                    0
        tcprcvbuf                  376832             21577728            293529600            440294400                    0
        othersockbuf                52400               360896            146764800            293529600                    0
        dgramrcvbuf                     0                 6936             14676480             14676480                    0
        numothersock                   61                   95                57330                57330                    0
        dcachesize               28028491             50196571            457560436            503316480                    0
        numfile                       918                 2315               655360               655360                    0
        dummy                           0                    0                    0                    0                    0
        dummy                           0                    0                    0                    0                    0
        dummy                           0                    0                    0                    0                    0
        numiptent                      24                   24                 8448                 8448                    0

Что касается определения проблемы с производительностью, вот альбом данных о производительности - первые два изображения - это результат ATOP на середине теста blitz.io, а затем близкий к концу при максимальной нагрузке. Третье изображение - это отчет blitz.io. Четвертый и пятый одинаковые (отчет ATOP + blitz.io) для одного и того же статического объекта, но с отключенным SSL. Тесты blitz.io идут от 1 до 1000 параллелизма за 60 секунд. Хотя при включенном SSL есть заметные накладные расходы, я все еще не приближаюсь к той производительности, которую ожидаю - увеличение параллелизма на blitz.io делает ситуацию еще хуже. Так что я оставляю это на ваше усмотрение, не стесняйтесь спрашивать любые разъяснения и предлагать любые изменения, которые я могу попробовать и перепроверить :)

Поскольку событие MPM зависит от базовой конфигурации рабочего процесса - попробуйте следующую конфигурацию в качестве ограничивающего эксперимента, а затем, если изменения приведут к измеримой разнице, это будет означать, что это по крайней мере одно из узких мест. Затем его можно настроить дальше:

Это значения по умолчанию для Apache:

  • ServerLimit 16 - вы можете видеть это как достигнутое на отправленном вами изображении - измените на 50
  • StartServers 2 - это для первоначального запуска - измените на 5
  • MaxClients 150 - измените это на 300
  • MinSpareThreads 25 - изменить на 50
  • MaxSpareThreads 75 - изменить на 150
  • ThreadsPerChild 25 - изменить на 50

Поскольку мы меняемся в 2-3 раза, вы должны увидеть линейное улучшение примерно в такой же раз.

Правка - улучшенная конфигурация - MaxClients (теперь известный как MaxRequestWorkers) был ошибкой. Как только сервер действительно может принимать определенное количество клиентов, просто убедитесь, что количество дочерних процессов и потоков на ребенка не превышает этого числа.

  <IfModule mpm_event_module>
    StartServers          5
    ServerLimit          32
    MinSpareThreads      64
    MaxSpareThreads     128
    ThreadsPerChild      64
    ThreadLimit          64
    MaxRequestWorkers   2048
    MaxRequestsPerChild 20000
    ListenBacklog      4096
  </IfModule>