Nginx is a high-performance web server and reverse proxy with a robust connection limiting mechanism that effectively prevents a small number of users from consuming excessive server resources. In US cloud servers, Nginx allows for fine-grained configuration of connection limits, maintaining overall system stability even in high-concurrency scenarios.
The core mechanism for limiting the number of connections in Nginx is based on its built-in `ngx_http_limit_conn_module`. This module stores and maintains the connection state of each defined key-value pair using a shared memory area. In practice, the most common approach is to differentiate users based on their client IP addresses, as IP addresses generally represent individual users or user groups effectively. When a new connection arrives, Nginx checks if the current connection count for that IP address has exceeded a preset threshold. If it has, the server can return a specific error code or execute a predefined handling strategy. This mechanism provides fundamental protection for resource allocation at the network layer, preventing a single IP address from establishing too many connections and exhausting server resources.
The first step in configuring Nginx connection limits is defining the limit zone, which is done using the `limit_conn_zone` directive within the HTTP block. This directive requires specifying a key to determine how to differentiate between users, while also setting the size of the memory zone for storing state information. Limiting based on client IP is the most straightforward approach, as shown in the following configuration example:
http { limit_conn_zone $binary_remote_addr zone=per_ip:10m;
# Other HTTP level configurations...
}
In this configuration, the `$binary_remote_addr` variable represents the client's IP address, stored in binary form, which saves more memory than the string form of `$remote_addr`. `per_ip` is a custom zone name, and `10m` indicates that 10MB of shared memory is allocated for storing connection state. The memory size needs to be set appropriately based on the expected number of unique IPs processed. Generally, 10MB of memory can store approximately 32,000 32-byte state entries or 16,000 64-byte state entries.
After defining the limited zone, these limits need to be applied in the specific server or location block. Use the `limit_conn` directive to specify the limited zone to use and the maximum allowed concurrent connections. For example, to limit each IP address to a maximum of 10 connections at the same time, you can configure it like this:
server { listen 80; server_name example.com; limit_conn per_ip 10;
# Other server configurations...
location / {
# Request handling configuration
} location /download/ { limit_conn per_ip 5;
# Use stricter limits for download areas
}
}
This configuration allows setting global limits at the server level, while applying stricter limits to specific locations. For example, in the above configuration, normal requests are allowed 10 concurrent connections per IP, while download requests under the /download/ path are only allowed 5 concurrent connections per IP. This differentiated configuration is particularly suitable for fine-grained control of business scenarios with varying resource consumption.
When the number of user connections exceeds the limit, Nginx returns a 503 (Service Temporarily Unavailable) status code by default. However, in some scenarios, it may be necessary to customize the returned error page or status code. The `limit_conn_status` directive can modify the default 503 status code. For example, setting it to 444 means closing the connection directly without sending any response headers:
server { limit_conn per_ip 10; limit_conn_status 444; # Other configurations... }
For scenarios requiring a more user-friendly experience, the `error_page` directive can be used to customize error pages:
http { limit_conn_zone $binary_remote_addr zone=per_ip:10m;
server { limit_conn per_ip 10;
error_page 503 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
internal;
}
}
}
In real-world production environments, limiting based solely on IP addresses may not be precise enough, as multiple users may share the same public IP address (e.g., on a company or school network). In such cases, it's advisable to combine other variables to create more granular user identification. For example, combining IP address and User-Agent as the limit key:
http { limit_conn_zone $binary_remote_addr$http_user_agent zone=per_user:10m;
server { limit_conn per_user 5;
# Other configurations...
}
}
This combination method can more accurately distinguish different user devices under the same IP, providing a fairer resource allocation. However, it should be noted that overly complex key values will increase memory usage, and a balance needs to be found between accuracy and resource consumption.
Log recording and monitoring are important components of connection limiting policies. Nginx provides the `limit_conn_log_level` directive to control the level of connection limiting-related logs, with a default value of error. Starting with Nginx version 1.17.6, the `limit_conn_dry_run` directive was introduced, supporting dry run mode. In this mode, the number of connections is virtually unlimited, but connection status is still recorded in the shared memory area for easier capacity planning and testing:
http { limit_conn_zone $binary_remote_addr zone=per_ip:10m;
limit_conn_log_level warn;
limit_conn_dry_run on;
# Other configurations...
}
The embedded variable `$limit_conn_status` can be used to record the connection limit result for each request, and its value can be PASSED, REJECTED, or REJECTED_DRY_RUN. This variable can be added to the access log format for easier subsequent analysis and monitoring:
http { log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$limit_conn_status"'; access_log /var/log/nginx/access.log main;
# Other configurations...
}
For large-scale distributed systems, connection limiting on a single Nginx server may not be comprehensive enough, requiring consideration of implementing limiting policies at the entire infrastructure level. This may require configuring corresponding rules in load balancers, application firewalls, or dedicated rate-limiting services. The commercial version of Nginx Plus offers richer connection limiting features, including dynamic configuration and more granular control policies, suitable for large-scale enterprise applications.
Performance tuning is an indispensable aspect when implementing connection limiting. Too small a memory area will result in inaccurate tracking of all connections, while too large a memory allocation will waste resources. Monitoring shared memory usage is crucial and can be achieved through Nginx status modules or third-party monitoring tools. Furthermore, connection limiting should work in conjunction with other Nginx optimization measures, such as worker process count adjustments, keepalive connection optimization, and caching strategy configuration, to collectively improve overall server performance.
When implementing connection limiting policies, exemption mechanisms for special cases also need to be considered. For example, search engine crawlers, internal monitoring systems, or specific API clients may require higher connection limits. A whitelist mechanism can be created using the map module:
http { geo $limit { default 1; 10.0.0.0/8 0; 192.168.0.0/16 0;
} map $limit $limit_key { 0 ""; 1 $binary_remote_addr;
} limit_conn_zone $limit_key zone=per_ip:10m;
# Other configurations...
}
This configuration creates a whitelist, specifying that IP addresses within a network segment are not subject to connection limits, while other addresses are subject to normal limits. This flexibility ensures that critical services or internal systems are not affected by connection restrictions.
By properly configuring Nginx's connection limiting function, resource abuse is prevented, ensuring service stability and availability. Well-designed limiting policies can protect servers from overload risks caused by malicious traffic or misconfigurations, ensuring that all users share system resources fairly.