Nginx Optimization for high traffic websites

May 26, 2020

By Rishil Shaji, Devops Engineer

9 Steps to Optimize Nginx for better performance

Nginx is an open-source reverse proxy server, fast, lightweight, and the ideal replacement for Apache webserver.

Nginx and Apache comparison

Apache and Nginx are the two most common open source web servers in the world. Together, they are responsible for serving over 50% of the traffic on the internet.

  • NGINX is about 2.5 times faster than Apache
  • NGINX can be deployed as a standalone web server, and as a frontend proxy for Apache and other web servers
  • NGINX – Event-driven architecture
  • Apache – process‑or‑thread‑per‑connection approach

 

The following tweaks can be done to Nginx configuration for full performance.

  • Switch from TCP to UNIX domain sockets
  • Adjust Worker Processes
  • Setup upstream load balancing
  • Disable access log files
  • Enable GZip
  • Cache information about frequently accessed files
  • /etc/sysctl.conf tuning
  • Monitoring the no of connections
  1. Switch from TCP to Unix domain sockets

UNIX sockets have better performance over TCP, UNIX sockets have the ability to copy data and make fewer context switches by identifying the current machine, it also avoids some check and operations like TCP negotiation and routing, etc..

Eg:
For TCP domain sockets we use IP sockets server 127.0.0.1:8080; for changing the sockets to UNIX domain sockets we replace the IP with the port server socket file unix:/var/run/fastcgi.sock;

If you are using more than 1000+ connections per server use the TCP server because they scale better.

  1. Adjust Worker Processes

The worker process is responsible for processing the request. Adjusting the worker processes in the Nginx config file to the number of CPU cores will improve the performance. Use the below command to execute.

cat /proc/cpuinfo | grep processor

  1. Adjust Worker Connections

The max number of simultaneous connections for 1 worker process is 512. This enables you to serve 512 clients. For 2 processes you will be able to serve 1024 clients.

  1. Setup Upstream Load Balancing

Multiple upstream backends on the same machine produce higher throughput than a single backend. For example, if we have 1000 max children, we can divide the no across multiple backend files according to the weight that is specified.

Eg:
upstream backend {
server 10.1.0.101 weight=4;
server 10.1.0.102 weight=2;
server 10.1.0.103;
}

Here the first server is selected twice as often as the second, which again gets twice the requests compared to the third.

  1. Disable access log files

Access logging of high traffic websites involves high I/O and disk space. Instead of writing the access log to the disk immediately, we can buffer the log to the memory

ie: add buffer=size parameter to the access log directive to write log entries to disk when the memory buffer fills up. If you don’t want the access log you can use these to disable the access logging

access_log off;
log_not_found off;
error_log /var/log/nginx-error.log warn;

If you want access logging, but don’t want to write to the disk immediately you can buffer the log to the memory ie: write log entries to disk when the memory buffer fills up.
access_log /var/log/nginx/access.log main buffer=16k;

  1. Enable Gzip

Compression is a huge performance accelerator. Compressing responses often significantly reduce the size of transmitted data. We can specify the compression level in gzip_comp_level 6;, but increasing the gzip_comp_level too high will waste CPU cycle. You can specify the compression type, length, and compress proxied request.

  1. Cache information about frequently accessed files

Caching helps web server load faster. In Nginx, we can specify open_file_cache to the static web content, open_file_cache will cache metadata only. In this we can specify the validity, duration, caching of error pages. Three technique to cache content generated by the webserver

  • Moving content closer to users
  • Moving content to faster machines
  • Moving content off of overused machines
  1. PHP-FPM pool tuning

High traffic websites utilize a lot of processor power. The default PHP-FPM configuration will consume a lot of RAM and CPU resources. We can see the process that is been created by monitoring TOP, HTOP commands in Linux

Increase PHP-FPM performance by adjusting the following 4 values

  • max_children: the maximum number of children that can be alive
  • start_servers: the number of children created on startup.
  • min_spare_servers: the minimum number of children idle.
  • max_spare_servers: the maximum number of children in idle.

PHP-FPM can be tuned according to static and dynamic process. In static process we can set pm.max_children & pm.max_requests,

Eg:
pm = static
pm.max_children = 5

By setting pm.max_children 5 (fixed value) we are setting the maximum number of children that can be alive on the server. Similarly, we can kill and respawns processes after handling a certain number of requests by setting pm.max_requests In Dynamic process we are setting pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers, pm.process_idle_timeout. In dynamic process management we use:
pm = dynamic

We can calculate the Max process by the formula below:
Total Max Processes = (Total Ram – (Used Ram + Buffer)) / (Memory per php process)
Max request per process is unlimited by default, but it’s good to set some low value like 200 and avoid memory issues.

  1. /etc/sysctl.conf tuning

Cloud instances are not fully optimized for the full availability.ie: the default systems may fail under high load. So we need to perform sysctl tweaking for maximum concurrency. Here is the list of tweaking that can be done to sysctl configuration file.

  • Increase system IP port limits to allow for more connections
  • Number of packets to keep in the backlog before the kernel starts dropping them
  • Increase socket listen backlog
  • Increase TCP buffer sizes
  • Disable Ping-flood attacks
  • Do less swapping and use RAM
  1. Monitoring the number of connections

By using Cloudwatch metrics and Monitis we can monitor the logs, connections, resource usage, number of waiting threads, and also generate a notification when the threshold value exceeds.

Conclusion

NGINX performance optimization is an essential part of every business, by constantly monitoring and tweaking the server resources we will be able to reduce the cost and increase the performance of the server considerably.

0 0 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Categories