Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

10 Million hits a day with WordPress using a $15 VPS

Slide for my talk at Meetup Web Performance Turin, about tuning a LEMP stack to gain maximum performance

  • Login to see the comments

10 Million hits a day with WordPress using a $15 VPS

  1. 1. 10 Million hits a day with WordPress using a $15 VPS
  2. 2. $ whoami Paolo Tonin Sysadmin @bakeca.it
  3. 3. Starting a new WordPress Project is straightforward
  4. 4. 10 minutes setup deployed on a simple VPS
  5. 5. 10 minutes setup
  6. 6. Your website become popular
  7. 7. No Silver Bullet!
  8. 8. Modernize our stack
  9. 9. Modernize our stack From
  10. 10. Modernize our stack To LEMP
  11. 11. #1 PHP Optimization
  12. 12. Switch over PHP-FPM
  13. 13. #1 PHP-FPM PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites. * Built in from PHP 5.4
  14. 14. #1 PHP-FPM $ sudo apt-get install -y php7.1-fpm $ sudo yum install -y php-fpm # ps fax | grep fpm 833 ? Ss 0:08 php-fpm: master process (/etc/php-fpm.conf) 1778 ? S 0:02 _ php-fpm: pool www 1779 ? S 0:02 _ php-fpm: pool www 1780 ? S 0:02 _ php-fpm: pool www 1781 ? S 0:02 _ php-fpm: pool www
  15. 15. Let’s dive into some details
  16. 16. #1 PHP-FPM pm = dynamic Similar to Apache prefork
  17. 17. #1 PHP-FPM pm = ondemand Ideal for hosting many small websites with small amount of request
  18. 18. #1 PHP-FPM pm = static Fixed php-fpm process number to archieve your server’s max performance
  19. 19. #1 PHP-FPM ; /etc/php-fpm.d/www.conf [www] pm = static pm.max_children = 10 user = sitename group = sitename ; listen on unix socket over tcp socket listen = /var/run/php-fpm/sitename-php-fpm.sock listen.owner = sitename listen.group = nginx listen.mode = 0660
  20. 20. ; /etc/php-fpm.d/www.conf ; try to avoid memory leaks, it enables php-fpm process respawning pm.max_requests = 700 ; audit slow request with stack trace log slowlog = /var/log/php-fpm/sitename-slow.log request_slowlog_timeout = 30s ; similar to “max_execution_time”, it has more priority than php.ini max_execution_time request_terminate_timeout = 180 ; log PHP Warning, Error, Fatal (not by default) catch_workers_output = yes
  21. 21. #1.1 PHP Optimization PHP 7 + OpCache
  22. 22. ; enable-opcache-file ; php.ini opcache.memory_consumption = 512 opcache.max_accelerated_files = 10000 opcache.interned_strings_buffer = 128 opcache.file_cache = /var/tmp opcache.huge_code_pages =1 ; php-cli.ini for WP-CLI and cronjobs opcache.enable_cli = 1 opcache.file_cache = /var/tmp opcache.file_cache_only = 1 #1.1 PHP OpCache
  23. 23. #1.1 PHP OpCache ; sysctl.conf ; enable hugepages, PHP7 only vm.nr_hugepages = 512 # cat /proc/meminfo | grep Huge AnonHugePages: 6144 kB HugePages_Total: 512 HugePages_Free: 300 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB
  24. 24. #1.1 PHP OpCache # ps ef -o command,vsize,rss,size -C php-fpm COMMAND VSZ RSS SIZE php-fpm: master process (/e 933836 278428 6204 _ php-fpm: pool www 1031728 42692 92916 _ php-fpm: pool www 1026596 40596 87784 _ php-fpm: pool www 1025452 37780 86640 _ php-fpm: pool www 1026252 35368 87440 Check php-fpm Memory Consumption 40MB * 50 php-fpm processes = 2GB RAM
  25. 25. #2 Replace webserver 245 million total sites and counting… running on NGINX
  26. 26. #2 Replace webserver Many config examples on https://www.nginx.com/resources/ wiki/start/index.html
  27. 27. #2 Replace webserver * Netcraft Sept 2017
  28. 28. #2.1 nginx System config limits # /etc/security/limits.conf # overrides ulimit values #<domain> <type> <item> <value> nginx hard nofile 100000 nginx soft nofile 100000
  29. 29. #2.1 nginx Nginx config limits # nginx.conf user nginx; worker_processes auto; worker_rlimit_nofile 10000; events { worker_connections 16384; multi_accept on; use epoll; }
  30. 30. #2.1 nginx Gzip compression # nginx.conf (continue) gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 256; gzip_buffers 32 8k;
  31. 31. #2.1 nginx Limit filesystem activity for static contents # nginx.conf (continue) open_file_cache max=10000 inactive=10s; open_file_cache_valid 20s; open_file_cache_min_uses 2; open_file_cache_errors on;
  32. 32. #2.2 nginx Nginx as reverse proxy
  33. 33. #2.2 nginx HTTP Caching primer
  34. 34. Expires: contains the datetime after which the response is considered stale. It has priority over Cache-Control Cache-Control: used to specify directives for caching mechanism in both, request and response
  35. 35. Last-Modified: contains the date and time at which the origin server believes the resource was last modified. HTTP dates are always expressed in GMT ETag: it’s an identifier for a specific version of a resource
  36. 36. proxy_cache_path /tmp/cache keys_zone=one:10m levels=1:2 inactive=60m; server { listen 80; server_name mywordpressdomain.com location / { proxy_pass http://localhost:8080 proxy_cache one; } } #2.2 nginx HTTP Caching primer
  37. 37. add_header X-Cache-Status $upstream_cache_status MISS Response not found in cache; go to upstream and save the results in the cache STALE Serve the stale content from the cache, because the upstream is not responding correctly HIT Serve valid content, fresh content direct from cache #2.2 nginx HTTP Caching instrumentation
  38. 38. proxy_cache_path /tmp/cache keys_zone=one:10m levels=1:2 inactive=60m; server { listen 80; server_name mywordpressdomain.com location / { proxy_pass http://localhost:8080 proxy_cache one; add_header X-Cache-Status $upstream_cache_status; } } #2.2 nginx HTTP Caching primer
  39. 39. PURGE verb is not supported in the OSS version $ curl -X PURGE -D - “http://domain.com/*"
  40. 40. Cache dynamic contents with fastcgi-cache (microcaching) “Go Big or Go Home”
  41. 41. #2.3 nginx php-fpm fastcgi cache # ps fax | grep nginx 922 ? Ss 0:00 nginx: master process /usr/sbin/nginx - c /etc/nginx/nginx.conf 3988 ? S 0:00 _ nginx: worker process 3989 ? S 0:00 _ nginx: worker process 3990 ? S 0:00 _ nginx: cache manager process Cache Manager activated periodically to check the state of the cache. The cache manager removes the data that was accessed recently as well the cache considered inactive
  42. 42. #2.3 nginx php-fpm fastcgi cache ; nginx.conf http block upstream php-web { server unix:/var/run/php-fpm/sitename.sock weight=100; server unix:/var/run/php-fpm/sitename.sock weight=100; } fastcgi_cache_path /var/tmp/nginx-fastcgi-cache levels=1:2 keys_zone=WPCACHE:100m max_size=1024m inactive=1h;
  43. 43. #2.3 nginx php-fpm fastcgi cache ; creates a cache version with these discriminants fastcgi_cache_key "$scheme$request_method$host$request_uri; ; at least 1 request to populate with a new cache element fastcgi_cache_lock on; ; consider stale response errors fastcgi_cache_use_stale error timeout invalid_header http_500;
  44. 44. #2.3 nginx php-fpm fastcgi cache ; enables revalidation of expired cache with the "If-Modified-Since" and "If-None-Match" header fields. fastcgi_cache_revalidate on; ; no cache for redirects fastcgi_cache_valid 301 0; fastcgi_cache_valid 3m; ; cache only GET http verb fastcgi_cache_methods GET;
  45. 45. #2.3 nginx php-fpm fastcgi cache # WARNING: Ignore cache-control; without these fcgi_cache doesn't works fastcgi_ignore_headers Cache-Control Expires Set- Cookie; fastcgi_pass_header Cookie;
  46. 46. #2.3 nginx php-fpm fastcgi cache # WARNING: Ignore cache-control; without these fcgi_cache doesn't works fastcgi_ignore_headers Cache-Control Expires Set- Cookie; fastcgi_pass_header Cookie;
  47. 47. location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.*)$; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; fastcgi_param HTTPS off; fastcgi_intercept_errors on; fastcgi_pass php-web; # Enable fastcgi_cache fastcgi_cache WPCACHE; fastcgi_cache_bypass $no_cache; fastcgi_no_cache $no_cache; }
  48. 48. Bonus content
  49. 49. WordPress plugins WP Offload S3 copies files from your WordPress Media Library to Amazon S3 and rewrites URLs to serve the files from S3, CloudFront, or another CDN WP Offload S3
  50. 50. WordPress plugins Replacement for wpdb class. It supports partition of data as well as replication and read write splits Used for commercial service wordpress.com
  51. 51. WordPress plugins Cache database results into Memcached, it also support integration with CDN providers
  52. 52. “Talk is cheap, show me the code” (cit. Linus Torvalds)
  53. 53. Demo

×