5

My setup is Intel® Core™ i7-2600 and RAM 16 GB DDR3 RAM

varnish+nginx+php-fpm+apc for a not very heavy WordPress blog with W3 Total Cache and CDN

My problem is that after 55 hits per second according to blitz.io varnish starts giving out timeouts. CPU usage at this time is hardly 1%. Free memory at all time remains 10GB+.

I tried benchmarking php-fpm directly with result of 150 hits/s without any timeouts. But after that the CPU usage goes 100% and it stops responding.

Can you help me optimize it to handle more?

As I understand nginx has nothing to do over here so I haven't included its config.

php-fpm config

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";
}

# Called after a document has been successfully retrieved from the backend.
sub vcl_fetch {
    # Uncomment to make the default cache "time to live" is 5 minutes, handy
    # but it may cache stale pages unless purged. (TODO)
    # By default Varnish will use the headers sent to it by Apache (the backend server)
    # to figure out the correct TTL.
    # WP Super Cache sends a TTL of 3 seconds, set in wp-content/cache/.htaccess

    set beresp.ttl   = 24h;

    # Strip cookies for static files and set a long cache expiry time.
    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;
    }
 # If WordPress cookies found then page is not cacheable
    if (req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)") {
       # set beresp.cacheable = false;#versions less than 3
        #beresp.ttl>0 is cacheable so 0 will not be cached
        set beresp.ttl = 0s;
    } else {
        #set beresp.cacheable = true;
        set beresp.ttl=24h;#cache for 24hrs
    }

    # Varnish determined the object was not cacheable
        #if ttl is not > 0 seconds then it is cachebale
    if (!beresp.ttl > 0s) {
    #    set beresp.http.X-Cacheable = "NO:Not Cacheable";
    } else if ( req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)" ) {
        # You don't wish to cache content for logged in users
        set beresp.http.X-Cacheable = "NO:Got Session";
        return(hit_for_pass); #previously just pass but changed in v3+
    }  else if ( beresp.http.Cache-Control ~ "private") {
        # You are respecting the Cache-Control=private header from the backend
        set beresp.http.X-Cacheable = "NO:Cache-Control=private";
        return(hit_for_pass);
    } else if ( beresp.ttl < 1s ) {
        # You are extending the lifetime of the object artificially
        set beresp.ttl   = 300s;
        set beresp.grace = 300s;
        set beresp.http.X-Cacheable = "YES:Forced";
    } else {
        # Varnish determined the object was cacheable
        set beresp.http.X-Cacheable = "YES";
 if (beresp.status == 404 || beresp.status >= 500) {
        set beresp.ttl = 0s;
    }

    # Deliver the content
    return(deliver);
}

sub vcl_hash {
    # Each cached page has to be identified by a key that unlocks it.
    # Add the browser cookie only if a WordPress cookie found.
    if ( req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)" ) {
        #set req.hash += req.http.Cookie;
        hash_data(req.http.Cookie);
         }
}


# vcl_recv is called whenever a request is received
sub vcl_recv {
    # remove ?ver=xxxxx strings from urls so css and js files are cached.
    # Watch out when upgrading WordPress, need to restart Varnish or flush cache.
    set req.url = regsub(req.url, "\?ver=.*$", "");

    # Remove "replytocom" from requests to make caching better.
    set req.url = regsub(req.url, "\?replytocom=.*$", "");
 remove req.http.X-Forwarded-For;
    set    req.http.X-Forwarded-For = client.ip;

    # Exclude this site because it breaks if cached
    if ( req.http.host == "sr.ituts.gr" ) {
        return( pass );
    }

    # Serve objects up to 2 minutes past their expiry if the backend is slow to respond.
    set req.grace = 120s;
    # Strip cookies for static files:
    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);
    }
    # Remove has_js and Google Analytics __* cookies.
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
    # Remove a ";" prefix, if present.
    set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
    # Remove empty cookies.
    if (req.http.Cookie ~ "^\s*$") {
        unset req.http.Cookie;
    }
    if (req.request == "PURGE") {
        if (!client.ip ~ purgehosts) {
                error 405 "Not allowed.";
        }
#previous version ban() was purge()
        ban("req.url ~ " + req.url + " && req.http.host == " + req.http.host);
        error 200 "Purged.";
    }

    # Pass anything other than GET and HEAD directly.
    if (req.request != "GET" && req.request != "HEAD") {
        return( pass );
    }      /* We only deal with GET and HEAD by default */

    # remove cookies for comments cookie to make caching better.
    set req.http.cookie = regsub(req.http.cookie, "1231111111111111122222222333333=[^;]+(; )?", "");

    # never cache the admin pages, or the server-status page, or your feed? you may want to..i don't
    if (req.request == "GET" && (req.url ~ "(wp-admin|bb-admin|server-status|feed)")) {
        return(pipe);
    }
    # don't cache authenticated sessions
    if (req.http.Cookie && req.http.Cookie ~ "(wordpress_|PHPSESSID)") {
        return(lookup);
    }
    # don't cache ajax requests
    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 options

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"

I'm not sure where to start. Should I start by optimizing php-fpm and then go to varnish? Or is php-fpm at its max right now so I should start looking for the problem in varnish?

1
  • 1
    You should start looking for the cpu consumers, I would also do a performance test with varnish out of the way to measure its benefits and decide whether to keep it or not. Also see this related question: serverfault.com/questions/350322/…
    – Ochoto
    Jan 27, 2012 at 13:01

2 Answers 2

0

In config: Varnish Daemon options

After change follow specials parameter, and default. I see their the same

-1

I read here somewhere that to you can compute your max_children based on how much memory you're allotting APC's apc.shm_size. It appears to me you've got an awfully large value.

Type "free" and divide your memory by the amount of APC you're allotting. That would be your max_children.

I suggest starting low on apc.shm_size, say 32MB. Tweak it from there.

What is wrong in my php-fpm configuration?

1
  • 1
    Sorry, but this is totally bogus. APC uses shared memory, so each child won't be bigger than APC.shm_size. May 11, 2013 at 15:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .