While basic Nginx configurations are well-documented, this article explores more advanced techniques to enhance your web server's capabilities.
- Resolving Cross-Origin Resource Sharing (CORS)
When managing multiple domains or during development with separate frontend and backend environments, cross-domain issues often arise. Nginx can efficiently handle these CORS challenges.
To enable cros-origin requests in your Nginx configuration, add the following headers within a server block:
# Allow requests from any origin
add_header 'Access-Control-Allow-Origin' *;
# Enable credentials in cross-origin requests
add_header 'Access-Control-Allow-Credentials' 'true';
# Specify allowed HTTP methods
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
# Define permitted request headers
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
After reloading Nginx, your application will be able to make cross-domain requests seamlessly.
- Implementing Referer Validation for Hotlink Protection
The referer header in HTTP requests indicates the source page. Nginx can validate this header to prevent unauthorized hotlinking of your resources.
Here's a configuration example that validates referer requests for specific file types:
server {
listen 80;
server_name assets.example.com;
location / {
root /var/www/html;
index index.html;
}
location ~* \.(gif|png|jpg|jpeg|bmp)$ {
# Only allow requests from example.com domains
valid_referers server_names *.example.com;
if ($invalid_referer) {
return 404;
}
root /var/www/assets;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
- Building Tomcat Clusters with Nginx
One of Nginx's most powerful features is load balancing for Java application servers like Tomcat, enabling high concurrency and availability.
First, define your backend servers in an upstream block, then configure request forwarding:
Define Tomcat cluster servers
upstream backend_servers { server 10.0.0.101:8080; server 10.0.0.102:8080; server 10.0.0.103:8080; }
server { listen 80; server_name api.example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
<p>By default, Nginx uses round-robin balancing with equal weight for all servers, suitable when all servers have similar performance characteristics.</p>
<h2>5. Weighted Load Balancing</h2>
<p>When servers have different capacities, you can assign weights to distribute traffic proportionally:</p>
<code>upstream backend_servers {
server 10.0.0.101:8080 weight=1;
server 10.0.0.102:8080;
server 10.0.0.103:8080 weight=3;
}
</code>
<p>In this configuration, for every 5 requests, server 101 and 102 will each receive 1 request, while server 103 will receive 3 requests.</p>
<h2>6. Server Health Management</h2>
<p>Nginx provides several directives to manage server health status:</p>
<h3>Temporarily Removing Servers</h3>
<code>upstream backend_servers {
server 10.0.0.101:8080;
server 10.0.0.102:8080 down;
server 10.0.0.103:8080;
}
</code>
<h3>Backup Servers</h3>
<code>upstream backend_servers {
server 10.0.0.101:8080 backup;
server 10.0.0.102:8080;
server 10.0.0.103:8080;
}
</code>
<h3>Dynamic Health Checking</h3>
<code>upstream backend_servers {
server 10.0.0.101:8080 max_fails=3 fail_timeout=15s;
server 10.0.0.102:8080;
server 10.0.0.103:8080;
}
</code>
<p>With this configuration, server 101 will be temporarily removed if it fails 3 times within 15 seconds and will be tested for recovery after that period.</p>
<h2>7. Optimizing Throughput with Keepalive Connections</h2>
<p>To reduce connection overhead and improve performance, you can configure persistent connections to backend servers:</p>
<code>upstream backend_servers {
server 10.0.0.101:8080;
server 10.0.0.102:8080;
server 10.0.0.103:8080;
keepalive 50;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://backend_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
</code>
<p>This configuration maintains a pool of 50 persistent connections to backend servers, reducing TCP handshake overhead and improving throughput.</p>
<h2>8. Alternative Load Balancing Strategies</h2>
<p>Beyond round-robin, Nginx offers several other load balancing algorithms:</p>
<h3>IP Hash</h3>
<p>Ensures requests from the same client are always directed to the same server:</p>
<code>upstream backend_servers {
ip_hash;
server 10.0.0.101:8080;
server 10.0.0.102:8080;
server 10.0.0.103:8080;
}
</code>
<h3>URI-Based Hashing</h3>
<p>Distributes requests based on the requested URI:</p>
<code>upstream backend_servers {
hash $request_uri;
server 10.0.0.101:8080;
server 10.0.0.102:8080;
server 10.0.0.103:8080;
}
</code>
<h3>Least Connections</h3>
<p>Directs traffic to the server with the fewest active connections:</p>
<code>upstream backend_servers {
least_conn;
server 10.0.0.101:8080;
server 10.0.0.102:8080;
server 10.0.0.103:8080;
}
</code>