Nginx – php-fpm and nginx @ high CPU usage

nginxperformancePHPphp-fpmUbuntu

My server is with DigitalOcean with the following plan:

2 Core Processor
2 GB Memory

My website is receiving thousands of visitors, however, both CPU cores are @ 100%:

enter image description here

The issue seems to be with php-fpm and nginx: worker process. I've made dozens of optimizations to my server, however, I still can't get it to calm down.

Here is my nginx.conf:

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

events {
    worker_connections 2048;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

    access_log off;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    gzip_vary on;
    gzip_proxied expired no-cache no-store private auth;
    gzip_comp_level 2;
    gzip_min_length 1000;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Buffers
    ##

    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 8m;
    large_client_header_buffers 2 1k;

    ##
    # nginx-naxsi config
    ##
    # Uncomment it if you installed nginx-naxsi
    ##

    #include /etc/nginx/naxsi_core.rules;

    ##
    # nginx-passenger config
    ##
    # Uncomment it if you installed nginx-passenger
    ##

    #passenger_root /usr;
    #passenger_ruby /usr/bin/ruby;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Here are the options I have enabled in php-fpm's www.conf:

user = www-data
group = www-data
listen = /var/run/php5-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = ondemand
pm.max_children = 20
pm.start_servers = 2
pm.min_spare_servers = 1
pm.process_idle_timeout = 10s;
pm.max_requests = 500
request_terminate_timeout = 20

How can I keep my server from overloading? What else can I change?

Best Answer

Running PHP is expensive, in terms of CPU usage and RAM. Any time you can avoid invoking the PHP interpreter, you should. Caching is the primary way you do this, so long as the content isn't custom generated for every user.

My little AWS t2.micro can serve around 2500 pages per second from its Nginx cache, but about 20 pages per second if PHP (HHVM) has to be invoked. This caching reduces my monthly bill, because if I had to generate pages for each user I'd need a much more powerful instance size, which costs more.

Microcaching is one option that works well for a rapidly changing site. Caching for as little as 1 second can have huge benefits. Of course if your site is changing slowly increasing the cache time will reduce CPU load further.

Another options include: - Running a more efficient PHP interpreter - PHP7 or HHVM - Optimizing your PHP code - Running a CDN. This can offload static resources easily, and if you set your page headers (expiry time and caching status) and CDN up correctly it can serve pages directly. I use CloudFlare with a Page Rule that tells it to "Cache Everything" including HTML (which is generated by PHP). The results in a faster website for users, reduced CPU and bandwidth usage, and CloudFlare has a free plan that suits many people.

You can use other caching systems such as Varnish, which is often used with HAProxy for load balancing. There is some crossover between these two products - HAProxy can do some caching, Varnish can do some load balancing. More information about them here.