Nginx – 502 errors on WordPress / nginx / php5-fpm

nginxphp-fpmUbuntuWordpress

I've looked through lots of other Server Fault and Google results that all have talk about generally similar situations, but I can't quite find the insight that I'm looking for. I would appreciate any help that the community can provide, and don't want anyone thinking that I didn't do an exhaustive amount of research before asking for help. I truly appreciate anyone who takes the to respond and educate me on this.

Here's the situation:

I have a Digital Ocean server with an 8 core processor, 16 GB RAM, and 160 GB SSD. The server is running WordPress on nginx + php5-fpm on Ubuntu 14.04.2 LTS.

I've always used Apache in the past, so this is my first foray into nginx.

Anyway, the site is running fine but I'm getting 502 bad gateway errors occasionally, and have had reports that users are also experience this problem on an intermittent basis. I have fairly aggressive edge caching with CloudFlare, to limit the number of hits to the actual original server.

The nginx error logs show a common problem:

2015/07/03 17:38:51 [error] 4283#0: *74154 connect() to unix:/var/run/php5-fpm.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 173.245.xx.xx, server: www.mydomain.com, request: "GET /path/to/file HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:

I'm finding that these entries correspond with the 502 scenario, but what I can't figure out is how to effective tune the php5-fpm and nginx to support the traffic.

top shows %Cpu(s): fluctuating between 27% and 54% during the several different times that I've been monitoring.

Memory usage also seems fine to me; here's the output from free -h:

             total       used       free     shared    buffers     cached
Mem:           15G        15G       248M        71M       1.3G        11G
-/+ buffers/cache:       2.3G        13G
Swap:           0B         0B         0B

Finally, turning to the nginx configuration, based on what I read, I have the worker_processes set to 8, with 16192 worker_connections. Here's what the /etc/nginx/nginx.conf looks like:

user www-data;
worker_processes 8;
pid /run/nginx.pid;

events {
    worker_connections  16192;
    multi_accept        on;
    use                 epoll;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 15;
    types_hash_max_size 2048;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    gzip on;
    gzip_disable "msie6";
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

And here's the config from /etc/nginx/sites-available/default

fastcgi_cache_key "$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;
    listen 127.0.0.1 default_server;

    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    server_name my.website.com;
    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

    }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

}

Final note: There are virtual hosts running on this machine too, each of which has a similar site config with fastcgi caching, and each is running WordPress.

Adding the config file for one of the vhosts, at the suggestion of @pennywise. I'm leaving my comments inline.

fastcgi_cache_path /etc/nginx/cache/vhostdomain levels=1:2 keys_zone=vhostdomain:100m inactive=60m;

server {
    listen 80;
    listen [::]:80;

    root /usr/share/nginx/www.vhostdomain.com;
    index index.php index.html index.htm;

    server_name www.vhostdomain.com;
    server_namevhostdomain.com;

    access_log   /var/log/nginx/vhostdomain.com.access.log;
    error_log    /var/log/nginx/vhostdomain.com.error.log;

    set $skip_cache 0;

    # POST requests should always go to PHP
    if ($request_method = POST) {
        set $skip_cache 1;
    }   

    # If the URL contains the query strings params cb or clk, bypass the cache
    if ($query_string ~* "cb=|clk=") {
        set $skip_cache 1;
    }

    # If the URL contains the /ad/ directory, bypass cache
    if ($request_uri ~* "/ad/") {
        set $skip_cache 1;
    }   

    # Don't cache uris containing the following segments
    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
        set $skip_cache 1;
    }   

    # Don't use the cache for logged in users or recent commenters
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }

    location / {
        try_files $uri $uri/ /index.php?$args;
    }    

    location ~ \.php$ {
        try_files $uri =404; 
        include fastcgi_params;
        #fastcgi_pass 127.0.0.1:9000;
        fastcgi_pass unix:/var/run/php5-fpm.sock;

        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;

        fastcgi_cachevhostdomain;
        fastcgi_cache_valid  60m;

    }

    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        access_log off; log_not_found off; expires max;
    }

    location = /robots.txt { access_log off; log_not_found off; }
    location ~ /\. { deny  all; access_log off; log_not_found off; }    
}

Adding /etc/php5/fpm/pool.d/www.conf sans comments:

[www]
user = www-data
group = www-data
listen = /var/run/php5-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chdir = /

Best Answer

In your config you have two location blocks \.php$
This is most probably the culprit, combine them in one and you should be fine.

Sometimes staring long time at code/config files makes your mind misses something obvious.