The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and DynamoDB on OVH for Magento 2
Nginx Configuration for High-Traffic Magento 2 Deployments
Optimizing Nginx is paramount for any high-traffic Magento 2 instance, especially when hosted on infrastructure like OVH where granular control is key. We’ll focus on tuning worker processes, connection handling, caching, and static file serving.
Worker Processes and Connections
The `worker_processes` directive should ideally be set to the number of CPU cores available on your server. This allows Nginx to utilize all available processing power for handling requests. The `worker_connections` directive dictates the maximum number of simultaneous connections a worker process can handle. A common starting point is 1024, but this can be increased based on your server’s memory and expected load.
worker_processes auto; # Or set to the number of CPU cores
events {
worker_connections 4096; # Adjust based on server resources and load
multi_accept on;
use epoll; # For Linux systems
}
HTTP Request Buffers and Timeouts
Tuning buffer sizes and timeouts can prevent request processing issues and resource exhaustion. `client_body_buffer_size` and `client_header_buffer_size` should be sufficient for typical request sizes. `client_max_body_size` is crucial for handling file uploads. Long `keepalive_timeout` values can keep connections open, reducing overhead, but too high can tie up resources.
http {
# ... other http directives ...
client_body_buffer_size 10m;
client_header_buffer_size 1m;
client_max_body_size 100m; # Adjust for large file uploads
keepalive_timeout 65;
keepalive_requests 1000;
send_timeout 60s;
client_body_timeout 60s;
client_header_timeout 60s;
lingering_close off;
lingering_time 30s;
}
Gzip Compression and Caching
Enabling Gzip compression significantly reduces bandwidth usage and speeds up content delivery. Browser caching via `expires` headers is essential for static assets. We’ll also configure Nginx’s FastCGI cache for PHP-FPM responses, which can dramatically improve page load times for non-personalized content.
http {
# ... other http directives ...
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
# Static file caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public";
}
# FastCGI Cache configuration
fastcgi_cache_path /var/cache/nginx/magento levels=1:2 keys_zone=magento_cache:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 404 1m;
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
fastcgi_cache_revalidate on;
fastcgi_cache_min_uses 1;
fastcgi_cache_lock on;
# ... rest of your http configuration ...
}
PHP-FPM Configuration for Magento 2
Magento 2 is a PHP application, and its performance is heavily reliant on the PHP-FPM configuration. We’ll focus on process management, memory limits, and opcache settings.
Process Management
The choice between static, dynamic, and ondemand process management depends on your traffic patterns. For high-traffic, consistent loads, static is often preferred for its predictable performance. Dynamic can be a good compromise, while ondemand is best for sporadic traffic.
; /etc/php/[version]/fpm/pool.d/www.conf ; Example for static process management pm = static pm.max_children = 100 ; Adjust based on available RAM and CPU cores pm.start_servers = 20 ; Initial number of children pm.min_spare_servers = 10 pm.max_spare_servers = 30 pm.max_requests = 500 ; Restart child processes after this many requests ; Example for dynamic process management ; pm = dynamic ; pm.max_children = 100 ; pm.start_servers = 5 ; pm.min_spare_servers = 2 ; pm.max_spare_servers = 10 ; pm.max_requests = 500 ; pm.process_idle_timeout = 10s ; Example for ondemand process management ; pm = ondemand ; pm.max_children = 100 ; pm.process_idle_timeout = 10s ; pm.max_requests = 500
Memory Limits and OPcache
Magento 2 is memory-intensive. Ensure `memory_limit` is set appropriately. OPcache is non-negotiable for PHP performance. Tuning its size and revalidation frequency is critical.
; /etc/php/[version]/fpm/php.ini memory_limit = 512M ; Or higher, depending on your server's RAM and Magento's needs max_execution_time = 300 ; For long-running tasks like cron jobs ; OPcache settings opcache.enable=1 opcache.memory_consumption=128 ; MB, adjust based on your code base size opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.revalidate_freq=2 ; Check for file updates every 2 seconds (adjust for development vs. production) opcache.validate_timestamps=1 ; Set to 0 in production for maximum performance if you have a robust deployment process opcache.save_comments=1 opcache.enable_file_override=0
Gunicorn Configuration for Magento 2 (if applicable)
While PHP-FPM is the standard for Magento 2, some advanced setups might use Gunicorn as a WSGI HTTP Server, often in conjunction with a Python application that interfaces with Magento. If this is your scenario, here are key tuning parameters.
Worker Processes and Threads
Gunicorn’s worker count should align with your CPU cores. The `threads` parameter is specific to the `gthread` worker type and allows for concurrency within a single process.
# Example Gunicorn command line # gunicorn --workers 4 --threads 2 --bind 0.0.0.0:8000 myapp:app # --workers: Number of worker processes. Typically CPU cores. # --threads: Number of threads per worker (for gthread worker type). # --worker-class: 'sync' (default), 'eventlet', 'gevent', 'gaiohttp', 'gthread'. # 'gthread' is often used for I/O bound tasks. # --bind: Address and port to bind to. # --timeout: Request timeout in seconds. # --keep-alive: Number of requests a worker can handle before restarting. # --max-requests: Maximum number of requests a worker can handle before restarting. # --preload-app: Preload the application into worker memory. # --log-level: Logging level (debug, info, warning, error, critical). # --access-logfile: Path to access log file. # --error-logfile: Path to error log file.
DynamoDB Tuning for Magento 2 Caching and Sessions
DynamoDB can be a powerful backend for Magento 2’s session storage and caching, especially in distributed environments. Proper provisioning and indexing are crucial to avoid throttling and ensure low latency.
Provisioned Throughput and Auto Scaling
The most critical aspect of DynamoDB performance is its provisioned throughput (Read Capacity Units – RCUs and Write Capacity Units – WCUs). For Magento, session tables and cache tables can experience high write and read volumes. Auto Scaling helps manage this dynamically.
# Example AWS CLI command to update provisioned throughput
aws dynamodb update-table --table-name MagentoSessions \
--provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=50
# Example AWS CLI command to configure Auto Scaling
aws application-autoscaling put-scaling-policy --service-namespace dynamodb \
--resource-id table/MagentoCache \
--scalable-dimension dynamodb:table:WriteCapacityUnits \
--policy-name MagentoCacheWriteScaling \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
},
"ScaleInCooldown": 300,
"ScaleOutCooldown": 300
}'
aws application-autoscaling put-scaling-policy --service-namespace dynamodb \
--resource-id table/MagentoCache \
--scalable-dimension dynamodb:table:ReadCapacityUnits \
--policy-name MagentoCacheReadScaling \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "DynamoDBReadCapacityUtilization"
},
"ScaleInCooldown": 300,
"ScaleOutCooldown": 300
}'
Global Secondary Indexes (GSIs)
Magento’s caching mechanisms might rely on specific query patterns. If your DynamoDB tables are used for caching or session management, ensure that any necessary GSIs are created to support these access patterns efficiently. For instance, if you frequently query sessions by user ID, a GSI on `user_id` would be beneficial.
# Example DynamoDB CreateTable with GSI for sessions
{
"TableName": "MagentoSessions",
"AttributeDefinitions": [
{"AttributeName": "session_id", "AttributeType": "S"},
{"AttributeName": "user_id", "AttributeType": "S"},
{"AttributeName": "last_access", "AttributeType": "N"}
],
"KeySchema": [
{"AttributeName": "session_id", "KeyType": "HASH"}
],
"GlobalSecondaryIndexes": [
{
"IndexName": "UserSessionsIndex",
"KeySchema": [
{"AttributeName": "user_id", "KeyType": "HASH"}
],
"Projection": {
"ProjectionType": "ALL"
},
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10
}
},
{
"IndexName": "LastAccessIndex",
"KeySchema": [
{"AttributeName": "last_access", "KeyType": "HASH"}
],
"Projection": {
"ProjectionType": "ALL"
},
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10
}
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 50,
"WriteCapacityUnits": 25
}
}
Monitoring and Diagnostics
Continuous monitoring is key to identifying performance bottlenecks before they impact users. For Nginx, monitor access logs for slow requests and error logs for recurring issues. PHP-FPM can be monitored via its status page or logs. DynamoDB CloudWatch metrics are essential for tracking consumed capacity, throttled requests, and latency.
- Nginx: `access.log`, `error.log`, `ngx_http_stub_status_module`.
- PHP-FPM: `slowlog`, `error.log`, `status_path`.
- DynamoDB: CloudWatch metrics (ConsumedReadCapacityUnits, ConsumedWriteCapacityUnits, ThrottledRequests, Latency).
Regularly review these metrics to adjust configurations proactively. For instance, a spike in `ThrottledRequests` on DynamoDB indicates a need to increase provisioned throughput or optimize access patterns.