The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MySQL on Google Cloud for Magento 2
Nginx Configuration for Magento 2 on Google Cloud
Optimizing Nginx is crucial for serving Magento 2 efficiently, especially under load. We’ll focus on key directives that impact performance and security in a Google Cloud environment.
Worker Processes and Connections
The worker_processes directive controls how many worker processes Nginx will spawn. A common recommendation is to set this to the number of CPU cores available. For worker_connections, this defines the maximum number of simultaneous connections that each worker process can handle. Ensure this is set high enough to avoid connection exhaustion.
Example Nginx Configuration Snippet
worker_processes auto; # Or set to the number of CPU cores
events {
worker_connections 4096; # Adjust based on expected load and system limits
multi_accept on;
}
http {
# ... other http directives ...
}
Caching Strategies
Leveraging Nginx’s built-in caching can significantly reduce backend load. We’ll configure browser caching for static assets and consider proxy caching for dynamic content if appropriate, though Magento’s Varnish integration is often preferred for full-page caching.
Browser Caching for Static Assets
location ~* ^/(media|static)/ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
Gzip Compression and Brotli
Compressing responses reduces bandwidth usage and speeds up delivery. Gzip is standard, and Brotli offers superior compression ratios for text-based assets. Ensure your Nginx is compiled with Brotli support if you plan to use it.
Gzip Configuration
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; gzip_disable "msie6"; # Disable for older IE versions
Brotli Configuration (if compiled with module)
# Ensure brotli module is loaded brotli on; brotli_comp_level 6; brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; brotli_disable "msie6";
Security Headers and SSL/TLS
Implementing security headers and optimizing SSL/TLS configurations is paramount. Use strong ciphers and protocols, and configure HSTS.
SSL/TLS Configuration Example
ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; # Google DNS or your preferred resolver resolver_timeout 5s; # HSTS Header add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; # Other Security Headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none';" always; # Example CSP, tailor to your needs
Gunicorn/PHP-FPM Tuning for Magento 2
The application server (Gunicorn for Python-based frameworks, PHP-FPM for PHP) is the next critical layer. We’ll focus on tuning its worker processes and resource allocation.
Gunicorn Tuning (for Python-based Magento forks or custom apps)
Gunicorn’s worker class and number of workers significantly impact concurrency. For I/O-bound applications like web servers, the gevent or event worker classes are often preferred. The number of workers is typically set to (2 * number_of_cores) + 1 as a starting point.
Gunicorn Command Line Example
gunicorn --workers 3 --worker-class gevent --bind 0.0.0.0:8000 myapp:app
PHP-FPM Tuning
PHP-FPM offers several process management strategies: static, dynamic, and ondemand. For Magento 2, which can have high memory footprints and varying request loads, dynamic or static are generally recommended. dynamic offers a good balance, while static provides predictable performance at the cost of potentially higher idle resource usage.
PHP-FPM Configuration File (php-fpm.conf or pool.d/www.conf)
; For dynamic process management pm = dynamic pm.max_children = 100 ; Maximum number of children that can be started. pm.start_servers = 10 ; Number of children created at startup. pm.min_spare_servers = 5 ; Minimum number of servers that should be kept idle. pm.max_spare_servers = 20 ; Maximum number of servers that should be kept idle. pm.process_idle_timeout = 10s ; The timeout for children idle processes. ; For static process management (if you need predictable resource allocation) ; pm = static ; pm.max_children = 150 ; Fixed number of children to serve requests. ; Adjust based on your server's RAM and expected concurrent requests. ; Monitor memory usage closely. request_terminate_timeout = 120 ; Timeout for script execution (Magento can be slow) ; pm.max_requests = 500 ; Restart a child process after this many requests. Useful for memory leaks.
OpCache Configuration
OpCache is essential for PHP performance. Ensure it’s enabled and tuned appropriately. For Magento, a larger opcache.memory_consumption and a reasonable opcache.interned_strings_buffer are beneficial.
PHP OpCache Settings (in php.ini)
[opcache] opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=256 ; Increase for Magento, e.g., 256MB or 512MB opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.revalidate_freq=60 opcache.save_comments=1 opcache.load_comments=1 opcache.enable_file_override=0 opcache.validate_timestamps=1 ; Set to 0 in production for max performance if you have a deployment process that clears opcache
MySQL Tuning for Magento 2 on Google Cloud
Database performance is often a bottleneck. We’ll focus on key MySQL configuration variables relevant to Magento’s workload.
InnoDB Buffer Pool
The innodb_buffer_pool_size is the most critical setting for InnoDB. It caches data and indexes. A common recommendation is to set it to 50-70% of available RAM on a dedicated database server. For shared servers, adjust accordingly.
MySQL Configuration Snippet (my.cnf or my.ini)
[mysqld] # General Settings max_connections = 500 ; Adjust based on application needs and server capacity table_open_cache = 2000 table_definition_cache = 1000 thread_cache_size = 16 # InnoDB Settings innodb_buffer_pool_size = 4G ; Example: 4GB. Adjust based on available RAM (e.g., 0.7 * RAM) innodb_log_file_size = 512M ; Larger log files can improve write performance innodb_log_buffer_size = 16M innodb_flush_log_at_trx_commit = 1 ; For ACID compliance. Set to 2 for higher performance with slight risk on crash. innodb_flush_method = O_DIRECT ; Recommended for Linux with modern storage innodb_io_capacity = 2000 ; Adjust based on disk I/O capabilities (e.g., SSDs) innodb_io_capacity_max = 4000 # Query Cache (Deprecated in MySQL 5.7, removed in 8.0. Consider alternatives like Redis for caching.) # query_cache_type = 0 # query_cache_size = 0 # Temporary Tables tmp_table_size = 64M max_heap_table_size = 64M # Logging (Essential for troubleshooting) slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 2 ; Log queries taking longer than 2 seconds log_queries_not_using_indexes = 1
Query Optimization and Indexing
While not strictly a configuration setting, ensuring proper indexing is paramount. Magento’s EAV model can lead to complex queries. Regularly analyze slow queries using the slow_query_log and add appropriate indexes. Tools like pt-query-digest are invaluable for this analysis.
Connection Pooling
For high-traffic sites, managing database connections efficiently is key. Consider implementing connection pooling at the application level or using a proxy like ProxySQL if your architecture demands it. This reduces the overhead of establishing new connections for each request.
Google Cloud Specific Considerations
Leveraging Google Cloud’s managed services and infrastructure can further enhance performance and reliability.
Instance Sizing and Machine Types
Choose appropriate Compute Engine machine types. For web servers, general-purpose (N1, N2) or compute-optimized (C2) instances are good choices. For databases, memory-optimized (E2, N2, N2D) instances are often preferred. Monitor CPU, memory, and network utilization to right-size your instances.
Persistent Disks
Use SSD Persistent Disks for your database and application storage. For high-performance databases, consider local SSDs for temporary tables or specific workloads, but be aware of their ephemeral nature.
Cloud Load Balancing
Utilize Google Cloud’s HTTP(S) Load Balancer for distributing traffic across your Nginx instances. This provides global reach, SSL termination, and health checking capabilities. Configure health checks to point to a specific health check endpoint on your Nginx servers.
Managed Database Services (Cloud SQL)
For simpler deployments or to offload database management, consider using Cloud SQL for MySQL. It handles patching, backups, and replication. Ensure you select an instance size that meets your performance requirements and configure appropriate flags for optimization.
Monitoring and Alerting
Implement robust monitoring using Google Cloud’s operations suite (formerly Stackdriver). Monitor key metrics for Nginx (requests per second, error rates), PHP-FPM/Gunicorn (process count, request latency), and MySQL (connections, query throughput, buffer pool hit rate). Set up alerts for critical thresholds.