Performance Optimization Guide
# Introduction
This document is intended to provide comprehensive and systematic performance optimization guidance for users of Apusic Load Balancer V2.0.6 Standard Edition. By deeply analyzing performance bottlenecks at both the operating system level and the ALB configuration level, combined with optimization cases for typical business scenarios, it helps users solve the performance issues that may be encountered in high-concurrency environments.
The document covers a wide range of topics, from basic system parameter tuning to complex million-level concurrent connection optimization, from common timeout configurations to key keep-alive reuse strategies, as well as troubleshooting methods for various problems that may be encountered during performance testing. Through the guidance in this document, users can:
- Identify and resolve performance bottlenecks of ALB in high-concurrency scenarios
- Reasonably configure the operating system and ALB parameters to improve overall system performance
- Master keep-alive optimization strategies to effectively reduce system resource consumption
- Quickly locate and resolve common problems encountered during performance testing
- Implement corresponding optimization solutions according to specific business scenarios
# Intended Audience
This document is mainly intended for developers, operations personnel, and related management staff of Apusic Load Balancer, and applies to Linux system environments (including Kylin, UOS, OpenEuler, CentOS, Ubuntu, and other distributions). By systematically studying and applying the optimization recommendations in this document, users can significantly improve the performance of ALB, ensuring that the system maintains stable and efficient service capabilities under high-load conditions.
# Related Documents
To learn more about ALB V2.0.6 product information, please refer to the following ALB V2.0.6 product manual document set:
| No. | Manual Document | Description |
|---|---|---|
| 1 | ALB V2.0.6 Release Notes | Introduces the ALB product version update content. |
| 2 | ALB V2.0.6 Quick Start Guide | Briefly introduces how to quickly get started with ALB. |
| 3 | ALB V2.0.6 Installation Guide | Describes in detail how to install ALB on various operating systems, ALB service start/stop operations, and the product registration process. |
| 4 | ALB V2.0.6 Proxy Function Manual | Describes in detail the use, configuration, and management of ALB-related functions, as well as the use of supporting tools. |
| 5 | ALB V2.0.6 Console User Manual | Describes in detail the use and operation instructions of ALB console-related functions. |
| 6 | ALB V2.0.6 Developer Manual | Describes in detail ALB external APIs, the alb-cli command-line tool, and AI Agent integration methods. |
| 7 | ALB V2.0.6 Migration Guide | Describes in detail the instructions for migrating and upgrading from historical ALB versions to V2.0.6. |
| 8 | ALB V2.0.6 Operations Manual | Describes in detail ALB monitoring, operations, security hardening, and other operations instructions. |
| 9 | ALB V2.0.6 Performance Optimization Guide | Describes in detail ALB performance tuning instructions. |
# Technical Support
ALB products provide comprehensive technical support services. You can obtain technical support through the following methods:
Website: www.apusic.com
Phone: 400-855-5800
Email: support@apusic.com
Kingdee Cloud Community: https://vip.kingdee.com/?productId=73&productLineId=14&lang=zh-CN
When obtaining technical support, please provide the following information:
Your name
Company information and contact details
Operating system and its version
Product version number
Detailed information such as logs and screenshots of the exceptions and errors that occurred
# Performance Bottleneck Source Analysis (Detailed Explanation from Two Dimensions: Operating System + ALB)
Although ALB is known for its high performance, in high-concurrency, high-traffic, or complex business scenarios, its actual performance is often limited by two key aspects: operating system resource scheduling policies and the rationality of ALB's own configuration. These two influence each other and need to be tuned together.
Overall principles:
The operating system provides the "stage" (CPU, memory, network, file system, and other resources);
ALB is the "actor", and its performance depends on the stage conditions and its own choreography (configuration).
Ignoring either aspect may cause the performance to fall short of expectations.
# Operating System Level Bottlenecks
# File Descriptor (FD) Limit
# Why Does It Exist?
Linux limits the number of file descriptors that each process can open by default (usually 1024) to prevent resource exhaustion. Each TCP connection and static file handle occupies one FD.
When the number of concurrent connections exceeds the limit, ALB will reject new connections and record Too many open files in the error log.
# How to Modify?
# Edit the alb startup script and add the following two lines at the beginning of the script
# [ALB installation directory]/bin/start-alb.sh or start-alb-and-console.sh
ulimit -n 65536
ulimit -Hn 65536
# If using systemd, add LimitNOFILE=65536 at the end of [Service]
# Edit /etc/systemd/system/alb.service
[Service]
....
User=root
Type=forking
LimitNOFILE=65536 # Add this line
# After modification, use systemctl daemon-reload and then restart ALB
2
3
4
5
6
7
8
9
10
11
12
13
# How to Verify?
# View worker process FD limit
cat /proc/$(pgrep alb | tail -1)/limits | grep "open files"
# Real-time FD usage
lsof -p $(pgrep alb | tail -1) | wc -l
2
3
4
5
# TCP Connection Queue and Network Stack Parameters
# Why Does It Exist?
The kernel limits the number of incomplete connections through somaxconn (accept queue) and tcp_max_syn_backlog (SYN queue). The default value (such as 128) is very easy to become a bottleneck in high-concurrency scenarios, causing new connections to be dropped, which manifests as client connection timeouts.
# How to Modify?
# Edit /etc/sysctl.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_abort_on_overflow = 1 # Optional: RST immediately when the queue is full, making it easier to identify issues
2
3
4
Run sysctl -p to apply.
Meanwhile, in the ALB configuration file alb.conf, add the backlog parameter to the listening port configuration within the server block:
listen 80 backlog=65535;
Note: The
backlogparameter oflistenand the systemsomaxconntogether determine the accept queue length. The actual effective value ismin(somaxconn, backlog). It is recommended to keep them consistent.
# How to Verify?
ss -lnt # View Recv-Q (current accept queue length). If it continues to be close to the backlog value, the queue needs to be expanded
# TIME_WAIT Connection Accumulation
# Why Does It Exist?
The party that actively closes the connection enters the TIME_WAIT state (about 60 seconds) to ensure that residual data packets in the network will not interfere with new connections. In short-connection high-frequency request scenarios (such as mobile API), a large number of TIME_WAIT will exhaust the local port (ephemeral port range), resulting in Cannot assign requested address.
# How to Mitigate?
# Edit /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_fin_timeout = 15
2
3
4
After modification, use sysctl -p to apply. ⚠️ Disable
tcp_tw_recycle(deprecated and unsafe under NAT).
# How to Verify?
# Count the number of TIME-WAIT connections
ss -ant | awk '/TIME-WAIT/ {count++} END {print count+0}'
# View total connections and the number of timewait
ss -s
2
3
4
5
# CPU and Interrupt Affinity
# Why Does It Exist?
By default, the network card interrupt is concentrated on CPU0, causing a single core to be overloaded while other cores are idle. The alb multi-worker cannot make balanced use of multiple cores.
# How to Optimize?
Enable reuseport (recommended):
listen 80 reuseport;
The kernel automatically distributes new connections to each worker's independent socket, achieving load balancing. Or manually bind IRQ to different CPUs (advanced).
# How to Verify?
top # Observe whether the usage rate of each CPU core is balanced
# ALB Configuration Bottlenecks
# Improper Worker Process and Connection Count Configuration
# Why Does It Exist?
- worker_processes is set too few (such as 1), unable to utilize multiple cores;
- worker_connections is set too low, and a single worker cannot handle sufficient concurrency;
- worker_rlimit_nofile is not set, resulting in ALB still being subject to internal limits even if the system allows it.
# How to Optimize?
worker_processes auto; # Automatically match the number of CPU cores
worker_rlimit_nofile 131072; # Increase the internal FD limit, must be ≥ worker_connections × 2
events {
use epoll; # Linux must enable this
worker_connections 65536; # Maximum connections per worker
multi_accept on; # Accept multiple connections at once
}
2
3
4
5
6
7
8
# How to Verify?
- Theoretical maximum concurrency ≈ worker_processes × worker_connections / 2 (each reverse proxy connection requires two sockets: client and upstream)
- Combine with stress testing to observe whether the expected QPS is achieved
# Unreasonable Buffer Configuration
# Why Does It Exist?
- proxy_buffering off will cause backend responses to be forwarded directly in a streaming manner, increasing the coupling between client and backend and reducing throughput;
- Buffers that are too small (such as the default 4k/8k) cause frequent syscalls in large response body scenarios, increasing CPU overhead;
- Buffers that are too large will waste memory.
# How to Optimize?
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 32k; # Total buffer ≈ 256k, adjust according to business
proxy_busy_buffers_size 64k;
2
3
4
# How to Verify?
- Compare the QPS and latency with buffering enabled/disabled;
- Use strace -p <worker_pid> to observe the read/write system call frequency.
# Frequent Log Writing Causes I/O Bottleneck
# Why Does It Exist?
By default, one line of access log is written per request. Under high concurrency, disk I/O becomes a bottleneck, especially when the mechanical hard disk or cloud disk IOPS is limited. How to optimize?
# Option 1: Disable non-essential logs (use with caution in production)
access_log off;
# Option 2: Enable buffered writing
access_log logs/access.log main buffer=64k flush=5s;
2
3
4
5
6
# How to Verify?
iostat -x 1 # Observe whether %util and await decrease
2
# High SSL/TLS Handshake Overhead
# Why Does It Exist?
Each new HTTPS connection requires a complete TLS handshake (2-RTT), which is compute-intensive (especially RSA key exchange) and consumes a lot of CPU.
# How to Optimize?
ssl_session_cache shared:SSL:10m; # Sessions shared among workers
ssl_session_timeout 10m;
ssl_session_tickets on; # Enable ticket for fast resumption (pay attention to key rotation)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off; # Let the client prioritize efficient ciphers
keepalive_timeout 75s; # Reuse TCP+TLS connections
2
3
4
5
6
# How to Verify?
- Use openssl s_client -connect host:443 -reconnect to test session reuse;
- Compare the QPS gap between HTTPS and HTTP during stress testing to see if it narrows;
- Monitor CPU usage (whether %sys in top is too high).
# No Efficient Transmission Mechanism Enabled for Static Resources
# Why Does It Exist?
sendfile, tcp_nopush, etc. are not enabled, resulting in multiple copies of data by the kernel, increasing latency.
# How to Optimize?
sendfile on; # Zero-copy file transfer
tcp_nopush on; # Works with sendfile to accumulate data into complete packets before sending, reducing the number of packet headers and improving throughput for large files
tcp_nodelay on; # After sendfile completes or in dynamic content scenarios, disable the Nagle algorithm to send small packets immediately, reducing latency
open_file_cache max=10000 inactive=60s; # Cache file metadata
2
3
4
Note:
tcp_nopushandtcp_nodelayapply to different scenarios and do not conflict when enabled at the same time.tcp_nopushmainly takes effect when sendfile sends large files;tcp_nodelaytakes effect in dynamic content or small-packet scenarios after sendfile completes. The combination of the two can simultaneously optimize throughput and latency.
# How to Verify?
- Compare the static file download speed before and after enabling;
- Use perf or bpftrace to observe page faults and copy counts.
# Comprehensive Verification Methods
After completing any of the above optimizations, the effect must be verified in the following ways:
| Verification Target | Tool/Command | Metrics of Interest |
|---|---|---|
| Concurrent connection capability | wrk -c 10000 -t 10 -d 30s URL | Requests/sec, Latency |
| Connection queue status | ss -lnt | Whether Recv-Q is close to backlog |
| FD usage | lsof -p PID | wc -l | Whether it is close to the limit |
| CPU utilization balance | top or htop | Whether the load of each core is uniform |
| Network errors | netstat -s | grep -i drop | listen overflows, packet drops |
| ALB internal status | Enable stub_status | active/accepts/handled/requests |
| Disk I/O pressure | iostat -x 1 | %util, await |
# Summary
| Dimension | Typical Bottleneck | Optimization Direction |
|---|---|---|
| Operating system | FD limit, TCP queue, TIME_WAIT | Adjust limits, sysctl parameters |
| ALB configuration | Worker count, Buffer, Log, SSL | Properly configure the events/http modules |
# Timeout Control Optimization
# Performance Bottlenecks Caused by Improper Timeout Settings
ALB involves multiple timeout parameters, which act in two directions: Client ↔ ALB and ALB ↔ Upstream Service. Improper configuration will cause:
- Connections cannot be released in time →
worker_connectionsexhausted; - Requests get stuck without returning → Client timeout, poor user experience;
- When the backend is abnormal, ALB accumulates a large number of pending requests → Memory/CPU exhaustion.
# Client-side Timeouts
| Parameter | Default | Function | Risk |
|---|---|---|---|
client_header_timeout | 60s | Timeout for reading client request headers | Slowloris attacks can exhaust connections |
client_body_timeout | 60s | Timeout for reading client request body | When large file uploads are not rate-limited, the worker gets stuck |
keepalive_timeout | 75s | Client keep-alive connection hold time | If set too large, idle connections will accumulate |
# ✅ Optimization Suggestions:
# Adjust according to business; the API scenario can be shortened
client_header_timeout 10s;
client_body_timeout 10s;
# Set keepalive reasonably, balancing reuse and resource reclamation
keepalive_timeout 30s; # Hold for 30 seconds
keepalive_requests 1000; # A single connection handles at most 1000 requests (to prevent memory leaks)
2
3
4
5
6
7
8
# 🔍 Verification Method:
- Simulate slow requests (such as using curl to limit the speed to send a large file slow.txt[10MB]:
curl --limit-rate 1k --data-binary @slow.txt -X POST http://ip:port/api); - Observe whether
client timed outappears in the error log; - Use
ss -o state establishedto check whether the ESTAB time of the connection exceeds expectations.
# Upstream Service Timeouts
| Parameter | Default | Function | Risk |
|---|---|---|---|
proxy_connect_timeout | 60s | Timeout for establishing a TCP connection with the upstream | Worker is blocked when the backend is down |
proxy_send_timeout | 60s | Timeout for sending requests to the upstream | Network congestion or slow backend reception |
proxy_read_timeout | 60s | Timeout for reading responses from the upstream | Backend processing is slow or hangs |
⚠️ The default 60s is extremely dangerous in high-concurrency scenarios! A slow interface may cause thousands of connections to be occupied.
# ✅ Optimization Suggestions (Taking an API Gateway as an Example):
location /api/ {
proxy_pass http://backend;
# Connection timeout: 1~3s is usually enough for a healthy backend on the intranet. If the backend is across data centers or the network quality is poor, it can be relaxed to 10s
proxy_connect_timeout 10s;
# Send/Read timeout: It is recommended to set it according to the business P99 in API scenarios (such as 500ms ~ 5s); for large file uploads or high-concurrency time-consuming business scenarios, it can be relaxed to 60s ~ 120s
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Other necessary configurations
proxy_http_version 1.1;
proxy_set_header Connection "";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 🔍 Verification Method:
- Set
proxy_read_timeoutto 5s, then let the backend sleep for 10s, and observe whether ALB returns 504 Gateway Timeout after 5s; - Monitor whether the active connections in alb_status surge during anomalies;
- The log should contain
upstream timed out (110: Connection timed out).
💡 Best Practice:
The timeout should be slightly greater than the backend P99 response time, and should be combined with a circuit breaker/degradation mechanism.
# Keep-Alive Configuration Guide
Keep-alive needs to be configured cooperatively in three links to take effect:
[Client] ←(HTTP Keep-Alive)→ [ALB] ←(Upstream Keep-Alive)→ [Upstream Service]
# Client ↔ ALB: Enable HTTP Keep-Alive
ALB supports client keep-alive by default, but it needs to be configured reasonably:
http {
# Global keepalive settings
keepalive_timeout 30s; # Connection hold for 30 seconds
keepalive_requests 1000; # A single connection handles at most 1000 requests (to prevent memory leaks)
# HTTP/2 multiplexing is automatically enabled, no additional configuration required
}
2
3
4
5
6
7
✅ Applicable to Web browsers, mobile apps, internal service calls, and other clients that support keep-alive.
# ALB ↔ Upstream: Enable Upstream Keep-Alive (Key!)
It has been described in detail earlier. Here it is integrated into a complete template:
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
keepalive 64; # Each worker caches 64 idle connections
}
server {
location /api/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # Clear the Connection header
# Timeout control (must be combined with keep-alive)
proxy_connect_timeout 3s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Backend Service: Needs to Support HTTP/1.1 and Maintain Connections
- Backend frameworks (such as Spring Boot, Gin) usually support it by default; frameworks such as Flask need to confirm the configuration and enable multi-thread/multi-process mode;
- Ensure that Connection: close is not actively sent;
- If TLS is used, it is recommended to enable session resumption.
# Comprehensive Verification: How to Confirm That Keep-Alive and Timeout Configurations Are in Effect?
| Verification Target | Method |
|---|---|
| Client keep-alive | Use browser developer tools or curl -v to check whether connections are reused; or use tcpdump to observe multiple HTTP requests in the same TCP stream |
| Upstream keep-alive | ss -tnp \| grep alb \| grep :8080 to check whether ESTAB connections are stably present |
| Timeout in effect | Simulate backend latency > timeout, and confirm that ALB returns 504 instead of hanging |
| Connection reuse effect | Compare the QPS and CPU usage with keepalive enabled/disabled through stress testing |
Example stress test command (verifying upstream keepalive):
# High-concurrency short requests
wrk -t16 -c1000 -d30s --latency http://alb/api/fast-endpoint
# Observe metrics:
# - Requests/sec increases
# - The number of timewait in ss -s drops significantly
# - The number of backend accept() decreases
2
3
4
5
6
7
# Typical Scenario Optimization Cases
# Scenario 1: Web Site Access Acceleration Optimization
# Business Scenario Description
A company has deployed a portal website that contains a large number of static resources (images, CSS, JS files). The traffic has gradually increased, and users report that the page loads slowly.
# Optimization Goal
Improve the access speed of static resources, reduce server load, and improve user experience.
# Optimization Solution
- Enable static resource caching
http {
# Enable file caching
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
server {
listen 80;
root /var/www/html;
# Set caching for static resources
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- Enable gzip compression
http {
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
}
2
3
4
5
6
# Optimization Effect
- Static resource loading speed increased by more than 50%
- Server CPU usage reduced by 20%
- User page load time significantly shortened
# Scenario 2: API Gateway Performance Optimization
# Business Scenario Description
A company's API gateway needs to handle a large number of mobile requests, and during peak hours, responses are slow and some requests fail.
# Optimization Goal
Improve the concurrent processing capability of the API gateway and ensure service stability.
# Optimization Solution
- Adjust the system file descriptor limit
# Edit the alb startup script and add the following two lines at the beginning of the script # [ALB installation directory]/bin/start-alb.sh or start-alb-and-console.sh ulimit -n 65536 ulimit -Hn 655361
2
3
4- Optimize ALB configuration
worker_processes auto; worker_rlimit_nofile 65536; events { use epoll; worker_connections 4096; multi_accept on; } http { # Enable keep-alive reuse upstream api_backend { server 192.168.1.30:8080 max_fails=3 fail_timeout=10s; server 192.168.1.31:8080 max_fails=3 fail_timeout=10s; keepalive 32; } # Limit the request rate of a single IP (to prevent malicious interface scraping) limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; server { listen 80 reuseport; # API routing location /api/ { proxy_pass http://api_backend; # Enable HTTP/1.1 keep-alive proxy_http_version 1.1; proxy_set_header Connection ""; # Set timeouts reasonably proxy_connect_timeout 5s; proxy_send_timeout 120s; proxy_read_timeout 120s; # Limit the request rate of a single IP (to prevent malicious interface scraping) limit_req zone=api burst=20 nodelay; } } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Scenario 3: File Download Service Optimization
# Business Scenario Description
The enterprise needs to provide a large file download service. Users report that the download speed is slow and server resource consumption is high.
# Optimization Goal
Improve the large file download speed and reduce server resource consumption.
# Optimization Solution
- Enable large file optimization configuration
http { # Adjust buffer size (applicable to reverse proxy large file download scenarios) proxy_buffering on; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; # Enable chunked download support proxy_http_version 1.1; server { listen 80; # Static file direct download (use root, no proxy_* parameters required) location /downloads/ { root /data; # Support resumable downloads add_header Accept-Ranges bytes; # Special configuration for large file downloads location ~* \.(iso|zip|exe)$ { # Limit download speed (to prevent bandwidth from being fully occupied) limit_rate 2m; # Limit to 2MB/s # Enable zero-copy transfer to improve static file download performance sendfile on; tcp_nopush on; } } } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Optimization Effect
- Large file download speed increased by 60%
- Server memory consumption reduced by 30%
- Support for resumable downloads, improving user experience
# Scenario 4: ALB Reverse Proxying AAS Service Performance Optimization
Goal: Through operating system tuning + ALB configuration optimization, enable ALB to efficiently proxy the backend AAS service and support high-concurrency API requests.
# Operating System Level Tuning (Linux)
Increase the file descriptor limit
# Edit the alb startup script and add the following two lines at the beginning of the script
# [ALB installation directory]/bin/start-alb.sh or start-alb-and-console.sh
ulimit -n 100000
ulimit -Hn 100000
2
3
4
5
Optimize the TCP network stack
# Edit /etc/sysctl.conf and add the following content:
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
fs.file-max = 2097152
# Apply
sysctl -p
2
3
4
5
6
7
8
9
10
AAS Performance Optimization: Ensure that the AAS application server has keep-alive support enabled, and adjust the thread pool and connection pool size according to the actual business. For detailed optimization, please refer to the AAS product performance tuning document.
# ALB Configuration Optimization
user root;
worker_processes auto;
worker_rlimit_nofile 131072; # Must be ≥ worker_connections × 2
events {
use epoll;
worker_connections 65536;
multi_accept on;
}
http {
# Global timeout control (applies to client ↔ ALB)
client_header_timeout 120s; # Relax appropriately for large file upload scenarios
client_body_timeout 120s;
keepalive_timeout 300s; # Client keep-alive connection hold time
keepalive_requests 1000; # A single connection handles at most 1000 requests
upstream aas_backend {
server 192.168.1.100:8080 max_fails=3 fail_timeout=10s;
server 192.168.1.101:8080 max_fails=3 fail_timeout=10s;
server 192.168.1.102:8080 max_fails=3 fail_timeout=10s;
keepalive 128; # Each worker maintains 128 idle keep-alive connections
keepalive_requests 1000; # A single upstream connection handles at most 1000 requests
keepalive_timeout 75s; # Upstream idle connection timeout (applies to ALB ↔ backend)
}
server {
listen 8080 reuseport;
location / {
proxy_pass http://aas_backend/;
# Enable keep-alive with AAS
proxy_http_version 1.1;
proxy_set_header Connection "";
# Timeout settings (slightly greater than AAS processing time)
proxy_connect_timeout 10s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
# Pass client information
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Log buffered writing
access_log access.log main buffer=64k flush=5s;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# Stress Test Verification
# Use wrk to simulate high-concurrency requests
wrk -t16 -c2000 -d60s --latency http://your-alb-server:8080/api/test
# Observe metrics:
# - Whether Requests/sec is stably improved
# - ALB error log has no "too many open files"
# - ss -tnp | grep :8080 to check whether ESTAB connections are maintained (instead of a large number of TIME-WAIT)
2
3
4
5
6
7
# Scenario 5: ALB Million-Level Concurrent Connection Test (C1000K)
# Background
# ✅ Typical Business Scenarios:
- WebSocket long-connection gateway (such as chat, IoT device access)
- HTTP long polling service
- Server-Sent Events (SSE) push platform
- Microservice API gateway (high keep-alive connections)
# ⚠️ Important Prerequisite:
Million-level concurrency ≠ Million-level QPS. Here, it means simultaneously maintaining 1,000,000 TCP connections, each of which may communicate at a low frequency (such as a heartbeat once per minute), but must remain alive.
# ❗ Core Difficulty:
ALB needs to maintain two sockets for each connection: client ↔ alb + alb ↔ backend → Total FD count ≈ 2 × number of concurrent connections If upstream keepalive is not enabled, the backend has to bear the pressure of millions of connections (which is almost infeasible) It is necessary to compress the number of backend connections to a reasonable range through connection reuse (keep-alive pool)
# Solution
- ALB layer: Undertake million-level connection access, TLS termination, and routing distribution
- Backend layer: Only needs to handle active requests and communicates with ALB through a small-scale keep-alive pool
- Key strategy: Massive front-end connections + limited back-end connection pool
💡 Ideal ratio:
1,000,000 client connections → ALB → 1,000 ~ 10,000 upstream keep-alive connections (reuse ratio 100:1 ~ 1000:1)
# Comprehensive Operating System Tuning (Linux)
# File Descriptor (FD) — The Most Critical!
# Edit the alb startup script and add the following two lines at the beginning of the script
# [ALB installation directory]/bin/start-alb.sh or start-alb-and-console.sh
ulimit -n 150000
ulimit -Hn 150000
# Global file handle upper limit
echo 'fs.file-max = 2500000' >> /etc/sysctl.conf
echo 'fs.nr_open = 2500000' >> /etc/sysctl.conf
2
3
4
5
6
7
8
9
10
📌 ulimit is set to 150,000, but the global setting is 2,500,000?
Minimum number of connections for ALB million-level connections: million connections × 2 (client + upstream) = 2,000,000.
Number of ALB workers: ulimit sets the number of files that each process can open to 150,000, so 2,000,000 / 150,000 = 14 worker processes (that is, 16 or more CPU cores are recommended).
Set 2,500,000: In addition to the 2,000,000 file numbers required by ALB, the system itself and other services also need to open files, that is, the 2,500,000 open file count is the upper limit of the entire system file handle count.
# Network Stack Tuning
# /etc/sysctl.conf
net.core.somaxconn = 1000000
net.core.netdev_max_backlog = 50000
net.ipv4.tcp_max_syn_backlog = 300000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 2
# TIME-WAIT optimization (generated when ALB actively closes the client connection)
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_max_tw_buckets = 2000000
# Memory buffers (support large concurrency)
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
net.ipv4.tcp_rmem = 4096 16384 67108864
net.ipv4.tcp_wmem = 4096 16384 67108864
# Port range (if ALB also acts as a client to initiate connections)
net.ipv4.ip_local_port_range = 1024 65535
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
After modifying 1 and 2, run the following command to apply:
sysctl -p
# Kernel and Hardware Recommendations
- Linux kernel ≥ 4.5 (stable support for reuseport + epoll)
- CPU ≥ 16 cores (the context switch overhead of million-level connections is large)
- Memory ≥ 64GB (each connection is about 4~8KB, million connections are about 8GB, plus buffer and backend cache)
- Disable swap:
swapoff -a - Use SSD: reduce the I/O impact of logs or temporary files
# ALB Configuration Optimization
user root;
worker_processes auto; # Match the number of CPU cores (such as 16)
worker_rlimit_nofile 300000; # Number of files opened by a single worker, must be ≥ worker_connections × 2
error_log error.log warn;
events {
use epoll;
worker_connections 150000; # A single worker supports 150,000 connections (16 × 150,000 = 2,400,000)
multi_accept on;
}
http {
# Disable access log (during stress testing), or use asynchronous buffering
access_log off;
error_log error.log crit;
# Efficient transmission
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Client keep-alive (maintain long connections)
keepalive_timeout 300s; # Disconnect after 5 minutes of no operation
keepalive_requests 1000000; # Prevent single-connection memory leaks
# Upstream keep-alive pool (core!)
upstream backend_pool {
# Assuming 10 backends, each with max_conns=1000, the total backend connection upper limit is 10,000
server 192.168.1.20:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.21:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.22:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.23:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.24:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.25:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.26:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.27:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.28:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
server 192.168.1.29:8080 max_conns=1000 max_fails=3 fail_timeout=10s;
# Each worker maintains 625 idle keep-alive connections (16 workers × 625 = 10,000, matching the total max_conns)
keepalive 625;
}
server {
listen 8080 reuseport backlog=1000000;
location / {
proxy_pass http://backend_pool/;
# Enable upstream keep-alive (required!)
proxy_http_version 1.1;
proxy_set_header Connection "";
# Timeout settings (according to the business heartbeat interval)
proxy_connect_timeout 15s;
proxy_send_timeout 300s; # Set according to the request body size and network conditions
proxy_read_timeout 300s; # Set according to the backend business processing time, should be slightly greater than the backend P99 response time
# Pass necessary headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
✅ Key Point Description:
- keepalive 1000: each worker maintains 1000 upstream idle connections;
- max_conns=1000: limits the maximum number of connections to a single backend to prevent overload;
- proxy_send/read_timeout ≥ keepalive_timeout: avoid ALB closing the connection prematurely;
- reuseport: enables kernel-level load balancing and avoids accept lock contention.
# Backend Optimization
- Support keep-alive
# Common Problems and Avoidance
| Problem | Cause | Solution |
|---|---|---|
| ALB reports "too many open files" | Insufficient FD limit | Increase LimitNOFILE + worker_rlimit_nofile |
| Backend connection count surges | Upstream keepalive not enabled | Check proxy_http_version 1.1 + Connection "" |
| Connections are frequently disconnected | Timeout settings do not match | Ensure proxy_read_timeout ≥ keepalive_timeout |
| Single-core CPU 100% | reuseport not enabled | Add listen ... reuseport; |
| Slow TLS handshake | Session not reused | Enable ssl_session_cache + ssl_session_tickets |
# Summary
Summary: The Core Formula for Million-Level Concurrency in Reverse Proxy
Million-level concurrency = Operating system resources × ALB connection management × Upstream keep-alive reuse × Backend asynchronous capability
| Layer | Key Action |
|---|---|
| OS | Increase FD, optimize TCP, disable swap |
| ALB | reuseport + large worker_connections + upstream keepalive |
| Backend | Asynchronous model + keep-alive support + externalized state |
| Verification | Stress test + monitoring + log analysis |
# Performance Testing and Troubleshooting
# Summary of Diagnostic Commands
# View ALB error logs (key focus)
tail -f ALB installation directory/logs/error.log
# View the current connection status
ss -s
# View ALB process FD usage
lsof -p $(pgrep alb | head -1) | wc -l
# View the system FD limit
ulimit -n
cat /proc/sys/fs/file-max
# View TCP queue overflow (key!)
netstat -s | grep -i "listen.*overflows\|drop"
# View CPU core load
top
# View ALB version
ALB installation directory/sbin/alb -V
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Error Symptom: A large number of requests return 502 Bad Gateway during stress testing
# 🔍 Error Analysis
ALB cannot establish a connection with the upstream backend or communication fails;
Common causes:
- The backend service is down or the port is not listening;
- proxy_connect_timeout is too short, and the backend starts slowly;
- The number of backend connections reaches the upper limit (such as Tomcat maxConnections exhausted);
- DNS resolution fails (if the upstream uses a domain name).
# ⚙️ Solution
location / {
proxy_pass http://backend;
proxy_connect_timeout 15s; # Adjust according to the backend startup time
proxy_read_timeout 30s;
resolver 8.8.8.8 valid=30s; # If a domain name is used, explicitly specify DNS
}
2
3
4
5
6
# ✅ Verification Method
- View the ALB error log:
grep "502" logs/error.log | head -5
# Typical log: connect() failed (111: Connection refused)
2
- Manually use curl to test whether the upstream is reachable;
- Monitor the backend accept queue during stress testing: use ss -lnt to check whether Recv-Q overflows.
# Error Symptom: Stress testing is normal at the beginning, then QPS drops sharply and connections accumulate
# 🔍 Error Analysis
- ALB worker_connections or system file descriptor (FD) exhausted;
- accept() failed (24:
Too many open files) appears in the log; - Reason: The default worker_connections=1024 + system ulimit -n=1024 cannot support high concurrency.
# ⚙️ Solution
- Operating system level:
# Edit the alb startup script and add the following two lines at the beginning of the script
# [ALB installation directory]/bin/start-alb.sh or start-alb-and-console.sh
ulimit -n 100000
ulimit -Hn 100000
# If using systemd, add LimitNOFILE=100000 at the end of [Service]
# Edit /etc/systemd/system/alb.service
[Service]
....
User=root
Type=forking
LimitNOFILE=100000 # Add this line
# After modification, use systemctl daemon-reload and then restart ALB
2
3
4
5
6
7
8
9
10
11
12
13
ALB configuration
worker_rlimit_nofile 100000;
events {
worker_connections 65536;
}
2
3
4
# ✅ Verification Method
- Check the process FD limit:
cat /proc/$(pgrep alb | head -1)/limits | grep "open files"
- Monitor FD usage in real time:
lsof -p $(pgrep alb | head -1) | wc -l
- Observe whether "Too many open files" still appears in the error log during stress testing.
# Error Symptom: A large number of 504 Gateway Timeout occur during stress testing
# 🔍 Error Analysis
- ALB timed out waiting for the upstream response;
- The default proxy_read_timeout=60s, but the backend processing is slow or hangs;
- Under high concurrency, a small number of slow requests can bring down the entire worker.
# ⚙️ Solution
- Set timeouts reasonably (according to the business P99 response time):
proxy_connect_timeout 15s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
2
3
- Backend optimization: Introduce asynchronous processing and circuit breaker mechanism;
- Avoid long-tail requests: protect the backend through rate limiting (limit_req).
# ✅ Verification Method
- Set
proxy_read_timeoutto 5s, then let the backend sleep for 10s, and confirm whether ALB returns 504 after 5s; - View the error log:
grep "upstream timed out" error.log
# Error Symptom: The client reports "Connection reset by peer" or "Connection closed" during stress testing
# 🔍 Error Analysis
- ALB actively closed the connection, commonly seen in:
- The client sent an incomplete request (such as sending only the header but not the body);
- client_body_timeout or client_header_timeout is triggered;
- The backend returns an illegal response (such as a chunked encoding error).
# ⚙️ Solution
- Adjust client behavior (ensure a complete HTTP request);
- Relax timeouts appropriately (only for trusted intranets):
client_header_timeout 30s;
client_body_timeout 30s;
2
- Enable more detailed logs to locate problems:
error_log error.log debug;
# ✅ Verification Method
- Use tcpdump to capture packets and analyze the source of the RST packets;
- Compare the error details with debug log enabled/disabled.
# Error Symptom: After enabling upstream keepalive, QPS does not improve or even decreases
# 🔍 Error Analysis
- Configuration omission: proxy_http_version 1.1 is not set or the Connection header is not cleared;
- The backend does not support keep-alive: returns Connection: close;
- The keepalive connection pool is too small: new connections are frequently created, and the reuse rate is low.
# ⚙️ Solution
upstream backend {
server 192.168.1.10:8080;
keepalive 128; # Adjust according to QPS
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # Key!
}
2
3
4
5
6
7
8
9
10
# ✅ Verification Method
Check the upstream connection status:
ss -tnp | grep ':8080' | grep alb | grep ESTAB | wc -l- If the value is stably ≈ worker_processes × keepalive, it indicates that it is in effect;
Stress test comparison: QPS and TIME-WAIT count before and after enabling.
# Error Symptom: The system CPU sys% (kernel mode) is too high during stress testing, reaching 70%+
# 🔍 Error Analysis
- Frequent syscalls (such as read/write) cause large context switch overhead;
- Zero-copy mechanisms such as sendfile and tcp_nopush are not enabled;
- Frequent sending of small packets (Nagle algorithm is not optimized).
# ⚙️ Solution
sendfile on;
tcp_nopush on; # Send after accumulating data, reducing packets
tcp_nodelay on; # Send small packets immediately (applicable to dynamic content)
2
3
- Prefer
sendfilefor static resources; - For dynamic APIs,
tcp_nopushcan be disabled andtcp_nodelayenabled.
# ✅ Verification Method
- Use
perf topto observe whether the proportion of kernel functions (such astcp_sendmsg) decreases; - Compare the
%sysmetric insar -ubefore and after optimization.
# Error Symptom: Under multi-core CPU, only CPU0 is 100% loaded, and other cores are idle
# 🔍 Error Analysis
- reuseport is not enabled, and all connections are accepted by a single worker;
- Network card interrupts are concentrated on CPU0.
# ⚙️ Solution
listen 80 reuseport;
listen 443 ssl http2 reuseport;
2
# ✅ Verification Method
top # Observe whether the load of each CPU core is balanced
ss -lnt | grep :80 # Check whether there are multiple listening sockets (characteristic of reuseport)
2
# Performance Testing Error Quick Reference Table
| Error Symptom | Possible Cause | Key Check Command | Solution |
|---|---|---|---|
| A large number of 502 Bad Gateway | Backend unreachable / connection refused / DNS failure | curl -v http://backendgrep "connect.*failed" logs/error.log | Check the backend service status Set resolver (if a domain name is used) Increase proxy_connect_timeout |
A large number of 504 Gateway Timeout | Backend response is slow / hangs | grep "upstream timed out" logs/error.logss -tnp | grep :backend_port | Set a reasonable proxy_read_timeout (such as 60~120s)Introduce timeout and circuit breaker on the backend |
| QPS cannot go up, connections accumulate | FD exhausted / worker_connections insufficient | cat /proc/$(pgrep alb)/limits | grep openlsof -p $(pgrep alb) | wc -l | Increase the system ulimit -nConfigure worker_rlimit_nofileIncrease worker_connections |
| Stress test reports "Too many open files" | System or ALB file descriptor limit is too low | dmesg | tailsystemctl show alb | grep LimitNOFILE | Modify the system file descriptor size Configure systemd LimitNOFILE Restart ALB |
| HTTPS QPS is much lower than HTTP | TLS handshake not reused / cipher is inefficient | openssl s_client -connect host:443 -reconnect 2>/dev/null | grep Reused | Enable ssl_session_cacheEnable ssl_session_ticketsUse TLSv1.3 + ECDHE-AESGCM |
| Only a single CPU core is 100%, the rest are idle | reuseport not enabled / accept lock contention | topss -lnt | grep :80 (check whether there are multiple listening sockets) | Add listen 80 reuseport;Ensure Linux kernel version ≥ 3.9 |
| Enabling upstream keepalive is invalid | Missing HTTP/1.1 or Connection header not cleared | ss -tnp | grep :backend_port | grep ESTAB | wc -l | Configuration:proxy_http_version 1.1;proxy_set_header Connection "";keepalive N; in upstream |
| The client reports "Connection reset by peer" | Timeout triggered / incomplete request / backend abnormally closed | tcpdump -i any -nn port 80 -w debug.pcapgrep "client timed out" logs/error.log | Adjust client_header_timeout / client_body_timeoutEnsure that the stress test tool sends complete HTTP requests |
| TIME-WAIT connection count surges (>100,000) | Connections not reused / ALB is the active closer | ss -snetstat -ant | awk '/TIME-WAIT/ {count++} END {print count+0}' | Enable upstream keepalive Set net.ipv4.tcp_tw_reuse=1 Avoid ALB actively closing (let the client close) |
| Poor static file performance | Zero-copy not enabled / buffer is small | strace -p $(pgrep alb) 2>&1 | grep -E 'read|write' | Enable sendfile on;Set tcp_nopush on;Adjust open_file_cache |
# Performance Optimization Key Parameter List
Table description:
- Directive: ALB configuration directive, referring to the parameter name of the ALB function configuration.
- Context: The scope of the parameter.
| Scope Identifier | Corresponding Configuration Block | Description |
|---|---|---|
| main | Global configuration area | Global parameter configuration area at the top level of the configuration file, not contained in any block |
| events | Event model configuration block | Configured within the events{} block, used to set ALB event processing model parameters |
| http | HTTP service configuration block | Configured within the http{} block, used to set HTTP service and proxy related parameters |
| server | Virtual server configuration block | Configured within the server{} block, used to set HTTP virtual server parameters |
| location | URL matching configuration block | Configured within the location{} block, used to set processing parameters for specific URL paths |
| upstream | Upstream service configuration block | Configured within the upstream{} block, used to set the parameters of the backend server group for reverse proxy |
| stream | Layer 4 proxy configuration block | Configured within the stream{} block, used to set TCP/UDP layer 4 proxy parameters |
| main/http/server/location | Multi-level configuration area | Can be configured at any level of main, http, server, and location |
| http/server/location | HTTP configuration area | Can only be configured at the http, server, and location levels |
# Global and Process Control
| Directive | Context | Function Description | Default | Recommended Value | Notes |
|---|---|---|---|---|---|
worker_processes | main | Number of ALB worker processes | auto | auto or number of CPU cores (such as 8) | auto automatically matches the number of CPU cores; must be set for multi-core |
worker_rlimit_nofile | main | Maximum number of file descriptors per worker | No limit (inherited from the system) | 65536 ~ 262144 | Must be ≥ worker_connections × 2 (client + upstream) |
worker_cpu_affinity | main | Bind workers to specified CPU cores | Not bound | auto (or manual mask) | Reduce context switches, improve cache hit rate (optional) |
# Event Model (Events)
| Directive | Context | Function Description | Default | Recommended Value | Notes |
|---|---|---|---|---|---|
worker_connections | events | Maximum number of concurrent connections per worker | 512 | 10000 ~ 200000 | Total concurrency ≈ worker_processes × worker_connections |
use | events | Event-driven model | Automatically selected | epoll (Linux) | Must be explicitly set to epoll on Linux (although it is the default, it is recommended to write it out) |
multi_accept | events | Accept multiple connections at once | off | on | Cooperate with epoll to improve throughput and avoid starvation |
# HTTP Global Configuration
| Directive | Context | Function Description | Default | Recommended Value | Notes |
|---|---|---|---|---|---|
sendfile | http/server/location | Zero-copy transfer of static files | off | on | Must be enabled for static resource services, reducing kernel/user-mode copies |
tcp_nopush | http/server/location | Send after accumulating data (cooperate with sendfile) | off | on | Improve the efficiency of large file transfer, reducing small packets |
tcp_nodelay | http/server/location | Disable the Nagle algorithm, send small packets immediately | off | on (API scenario) | Recommended to enable for dynamic content/API, reducing latency |
open_file_cache | http/server/location | Cache file metadata (fd/stat) | off | max=10000 inactive=60s | Required for high-frequency static file access |
open_file_cache_valid | http/server/location | Cache validation interval | 60s | 30s ~ 120s | Used in conjunction with open_file_cache |
open_file_cache_min_uses | http/server/location | Minimum number of file accesses to cache | 1 | 2 | Prevent caching cold files |
# Client Connection and Timeout
| Directive | Context | Function Description | Default | Recommended Value | Notes |
|---|---|---|---|---|---|
keepalive_timeout | http/server/location | Client keep-alive connection hold time | 75s | 15s ~ 30s (Web API) 300s (long connection) | If set too large, idle connections will accumulate |
keepalive_requests | http/server/location | Maximum number of requests per connection | 100 | 1000 ~ 1000000 | Prevent single-connection memory leaks |
client_header_timeout | http/server/location | Timeout for reading request headers | 60s | 10s ~ 30s Can be increased under high concurrency, such as 120s | Prevent Slowloris attacks |
client_body_timeout | http/server/location | Timeout for reading request body | 60s | 10s ~ 120s For file uploads, it can be set according to the actual time | Needs to be increased for large file uploads, can be reduced for APIs |
reset_timedout_connection | http/server/location | Send RST instead of FIN after timeout | off | on | Quickly release TIME-WAIT (use with caution) |
# Reverse Proxy (Proxy)
| Directive | Context | Function Description | Default | Recommended Value | Notes |
|---|---|---|---|---|---|
proxy_http_version | http/server/location | HTTP version used by the proxy | 1.0 | 1.1 | Must be set to 1.1 to enable upstream keepalive |
proxy_set_header Connection "" | location | Clear the Connection header | None | "" | Used in conjunction with keepalive to prevent close |
proxy_connect_timeout | http/server/location | Timeout for establishing a connection with the upstream | 60s | 1s ~ 10s Can be increased under high concurrency, such as 120s | Fast failure on backend health check |
proxy_send_timeout | http/server/location | Timeout for sending requests to the upstream | 60s | 5s ~ 30s Can be increased under high concurrency, such as 120s | Set according to business P99 |
proxy_read_timeout | http/server/location | Timeout for reading responses from the upstream | 60s | 5s ~ 300s Can be increased for high concurrency or time-consuming business | Can be set larger for long-connection scenarios |
proxy_buffering | http/server/location | Whether to buffer backend responses | on | on (default) | Disabling will increase backend pressure, generally not disabled |
proxy_buffer_size | http/server/location | Size of the first buffer | 4k|8k | 16k | Contains the response header, recommended to be ≥ 16k |
proxy_buffers | http/server/location | Number and size of response body buffers | 8 4k|8k | 8 32k | Increase appropriately in high-throughput scenarios |
# Upstream Keep-Alive Pool
| Directive | Context | Function Description | Default | Recommended Setting Range | Notes |
|---|---|---|---|---|---|
keepalive | upstream | Number of idle keep-alive connections per worker | None | 32 ~ 256 | Total connection pool = worker_processes × keepalive |
keepalive_requests | upstream | Maximum number of requests per upstream connection | 1000 | 1000 (default, reasonable) | Prevent connection memory leaks |
keepalive_timeout | upstream | Upstream idle connection timeout | 60s | 60s (default, reasonable) | Usually no need to modify |
# Logs
| Directive | Context | Function Description | Default | Recommended Value | Notes |
|---|---|---|---|---|---|
access_log | http/server/location | Access log | logs/access.log combined | off (stress testing)or buffer=64k flush=5s | Disable or buffer writes under high concurrency |
error_log | main/http/server | Error log level | error | warn (production)crit (stress testing) | Avoid debug logs slowing down performance |