2016-08-08 10 views
1

Опытная проблема при загрузке ~ 4000 одновременно работающих пользователей на сайте WP. Вот конфигурация, которую у меня есть:Varnish cache - не может обрабатывать 4000 одновременных пользователей

F5 loadbalancer ---> Varnish 4 с 8 ядрами, RAM 32 ГБ ---> 9 backend с 4 ядрами, по 16 RAM каждый, работающий WP сайт.

В то время как нагрузка составляет ~ 2500-3000 пользователей, все идет нормально, без каких-либо ошибок, но когда пользователи достигают 4k, лак перестает отвечать, пока не вычислит все запрошенные в очереди запросы, плюс мы увидим много ошибок 502.

Имейте 2 бассейна по 5000 нитей; таНос = 30G

Additionaly добавил SOMAXCONN и TCP_MAX_SYN_Backlog в SYSCTL

Вот VCL:

vcl 4.0; 
import directors; 
import std; 
backend qa2 { .host = "xxx"; .port = "80"; } 
backend qa3 { .host = "xxx"; .port = "80"; } 
backend qa4 { .host = "xxx"; .port = "80"; } 
backend qa5 { .host = "xxx"; .port = "80"; } 
backend qa6 { .host = "xxx"; .port = "80"; } 
backend qa7 { .host = "xxx"; .port = "80"; } 
backend qa8 { .host = "xxx"; .port = "80"; } 
backend qa9 { .host = "xxx"; .port = "80"; } 
backend qa10 { .host = "xxx"; .port = "80"; } 

# .connect_timeout = 2s; .first_byte_timeout = 10m; .between_bytes_timeout = 10m; 

acl purge_list { 
    "xxx"; 
    "xxx"; 
    "xxx"; 
    "xxx"; 
    "xxx"; 
    "xxx"; 
    "xxx"; 
    "xxx"; 
    "xxx"; 
    "xxx"; 
} 
sub vcl_init { 
    new rr = directors.round_robin(); 
    rr.add_backend(qa2); 
    rr.add_backend(qa3); 
    rr.add_backend(qa4); 
    rr.add_backend(qa5); 
    rr.add_backend(qa6); 
    rr.add_backend(qa7); 
    rr.add_backend(qa8); 
    rr.add_backend(qa9); 
    rr.add_backend(qa10); 
} 

sub vcl_recv { 
    set req.backend_hint = rr.backend(); 
if (req.method == "PURGE") { 
     if (!client.ip ~ purge_list) { 
      return(synth(405, "not allowed.")); 
     } 
     ban("req.url ~ .css"); 
     return(synth(200, "CSS Files Cleared from Cache!")); 
    } 
    # Don't check cache for POSTs and various other HTTP request types 
    if (req.method != "GET" && req.method != "HEAD") { 
    #ban("req.http.host == " + req.http.host); 
    return(pass); 

    } 
    # Don't check cache for POSTs and various other HTTP request types 
    if (req.http.Cookie ~ "SESS[a-f|0-9]+" || 
    req.http.Authorization || 
    req.url ~ "login" || 
    req.method == "POST" || 
    req.http.Cookie || 
    req.url ~ "/wp-(login|admin)") { 
    return (pass); 
    } 
    if (req.http.Accept-Encoding) { 
    if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") { 
      unset req.http.Accept-Encoding; 
     } elsif (req.http.Accept-Encoding ~ "gzip") { 
      set req.http.Accept-Encoding = "gzip"; 
     } elsif (req.http.Accept-Encoding ~ "deflate") { 
      set req.http.Accept-Encoding = "deflate"; 
     } else { 
      unset req.http.Accept-Encoding; 
     } 
    } 

    if (req.url ~ "\.(aif|aiff|au|avi|bin|bmp|cab|carb|cct|cdf|class|css)$" || 
     req.url ~ "\.(dcr|doc|dtd|eps|exe|flv|gcf|gff|gif|grv|hdml|hqx)$" || 
     req.url ~ "\.(ico|ini|jpeg|jpg|js|mov|mp3|nc|pct|pdf|png|ppc|pws)$" || 
     req.url ~ "\.(swa|swf|tif|txt|vbs|w32|wav|wbmp|wml|wmlc|wmls|wmlsc)$"|| 
     req.url ~ "\.(xml|xsd|xsl|zip|woff)($|\?)") { 
     unset req.http.Cookie; 
     #unset req.http.Authorization; 
     #unset req.http.Authenticate; 
     return (hash); 
    } 

    return(hash); 
} 

# Cache hit: the object was found in cache 
sub vcl_hit { 
    if (req.method == "PURGE") { 
     return (synth(200, "Purged!")); 
    } 
} 
# Cache miss: request is about to be sent to the backend 
sub vcl_miss { 
    if (req.method == "PURGE") { 
     return (synth(200, "Purged (Not in cache)")); 
    } 
} 
sub vcl_backend_response { 
    if (bereq.url ~ "\.(aif|aiff|au|avi|bin|bmp|cab|carb|cct|cdf|class|css)$" || 
     bereq.url ~ "\.(dcr|doc|dtd|eps|exe|flv|gcf|gff|gif|grv|hdml|hqx)$" || 
     bereq.url ~ "\.(ico|ini|jpeg|jpg|js|mov|mp3|nc|pct|pdf|png|ppc|pws)$" || 
     bereq.url ~ "\.(swa|swf|tif|txt|vbs|w32|wav|wbmp|wml|wmlc|wmls|wmlsc)$"|| 
     bereq.url ~ "\.(xml|xsd|xsl|zip|woff)($|\?)") { 
    set beresp.grace = 30s; 
    set beresp.ttl = 1d; 
    set beresp.http.Cache-Control = "public, max-age=600"; 
    set beresp.http.expires = beresp.ttl; 
    return (deliver); 
    } 
} 
# Deliver the response to the client 
sub vcl_deliver { 
    # Add an X-Cache diagnostic header 
    if (obj.hits > 0) { 
    set resp.http.X-Cache = "HIT"; 
    set resp.http.X-Cache-Hits = obj.hits; 
    # Don't echo cached Set-Cookie headers 
    unset resp.http.Set-Cookie; 
    } else { 
    set resp.http.X-Cache = "MISS"; 
    } 
    # Remove some headers not needed on production systems 
    # unset resp.http.Via; 
    # unset resp.http.X-Generator; 
    # return(deliver); 
}* 

А вот результаты последнего теста:

enter image description here

enter image description here

На самом деле время отклика хорошее, но пропускная способность плохая, и, как я уже писал, Varnish зависает, пока не завершит решение всех предыдущих запросов.

Итак, вопросы: есть ли теоретический предел для лаковых параллельных пользователей? Как настроить его для работы с более чем 4k параллельными соединениями?

PS. Также расширены MaxClients на каждом сервере Apache.

ответ

0

Лак никогда не произведет код возврата 502, что означает, что вы, скорее всего, не кешируете ответы.

Возможно, вы можете провести сравнительный анализ своего бэкэнда.

Нет встроенных ограничений по количеству одновременных пользователей. Количество ваших потоков отлично выглядит. Для всего 4000 сеансов вам не нужно делать какие-либо настройки ядра/ОС, значения по умолчанию должны быть точными. Если вы нажмете somaxconn, это, скорее всего, артефакт ваших инструментов бенчмаркинга и, вероятно, не будет иметь места на реальном трафике.

Подведение итогов: проверьте количество попаданий и посмотрите на лак, чтобы выяснить, почему вещи не кешируются.

+0

Да, жаль я не говоря уже о том, что hitrate просто отлично, более 90% HIT, поэтому лак обычно кэшируется. Между тем, загрузка бэкэндов не превышает 60-70% на каждой машине, все кажется хорошим. Есть предположения? –

0

502 Плохой шлюз означает, что ваш бэкэнд в какой-то мере не работает, и Лак не может подключиться, что, вероятно, является причиной его замерзания с огромной очередью.

Я замечаю здесь вы передаете что-нибудь с набором печеньем в vcl_recv:

# Don't check cache for POSTs and various other HTTP request types 
    if (req.http.Cookie ~ "SESS[a-f|0-9]+" || 
    req.http.Authorization || 
    req.url ~ "login" || 
    req.method == "POST" || 
*** req.http.Cookie || 
    req.url ~ "/wp-(login|admin)") { 
    return (pass); 
    } 

Особенно с Wordpress это собирается убить hitrate и вызвать массу серверных соединений, так как лак не будет кэшировать печенье.

Вот некоторые примеры кода мы используем vcl_recv обрабатывать печенье:

# Pass if the page is login, admin, preview, search or xmlrpc 
if (req.url ~ "wp-(login|admin|json)" || req.url ~ "preview=true" || req.url ~ "\?s=" || req.url ~ "xmlrpc.php" || req.http.Cookie ~ "wordpress_logged_in_") { 
    return (pass); 
} 

# Some wordpress URL manipulation 
if (req.url ~ "\?(utm_(campaign|medium|source|term)|adParams|client|cx|eid|fbid|feed|ref(id|src)?|v(er|iew))=") { 
    set req.url = regsub(req.url, "\?.*$", ""); 
} 

# Some generic URL manipulation, useful for all templates that follow 
# First remove the Google Analytics added parameters, useless for our backend 
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") { 
    set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", ""); 
    set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?"); 
    set req.url = regsub(req.url, "\?&", "?"); 
    set req.url = regsub(req.url, "\?$", ""); 
} 

# Strip hash, server doesn't need it. 
if (req.url ~ "\#") { 
    set req.url = regsub(req.url, "\#.*$", ""); 
} 

# Strip a trailing ? if it exists 
if (req.url ~ "\?$") { 
    set req.url = regsub(req.url, "\?$", ""); 
} 

# Remove the wp-settings-1 cookie 
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(;)?", ""); 

# Remove the wp-settings-time-1 cookie 
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(;)?", ""); 

# Remove the wp test cookie 
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(;)?", ""); 

# Remove the cloudflare cookie 
set req.http.Cookie = regsuball(req.http.Cookie, "__cfduid=[^;]+(;)?", ""); 

# Remove the PHPSESSID in members area cookie 
set req.http.Cookie = regsuball(req.http.Cookie, "PHPSESSID=[^;]+(;)?", ""); 

# Remove the Quant Capital cookies (added by some plugin, all __qca) 
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(;)?", ""); 

# Are there cookies left with only spaces or that are empty? 
if (req.http.cookie ~ "^\s*$") { 
    unset req.http.cookie; 
} 

# Unset Cookies except for WordPress admin and WooCommerce pages 
if (!(req.url ~ "(wp-login|wp-admin|cart|my-account/*|checkout|addons|wordpress-social-login|wp-login\.php|forumPM|members|logout|lost-password|product/*)")) { 
    unset req.http.cookie; 
}  

Этого должно быть достаточно, чтобы добавить к vcl_backend_response:

# Unset Cookies except for WordPress admin and WooCommerce pages 
if ((!(bereq.url ~ "(wp-(login|admin)|login|cart|my-account/*|checkout|addons|logout|lost-password|product/*)"))) { 
    unset beresp.http.set-cookie; 
} 
+0

Большое спасибо, попробуем это сегодня. –