• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MySQL on OVH for C++

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MySQL on OVH for C++

Nginx Configuration for High-Traffic C++ Applications

Optimizing Nginx is crucial for serving C++ applications, especially when they are fronted by WSGI/FastCGI servers like Gunicorn or PHP-FPM. The primary goals are efficient request handling, robust connection management, and effective caching.

Worker Processes and Connections

The worker_processes directive determines how many worker processes Nginx will spawn. A common best practice is to set this to the number of CPU cores available on your server. For OVH instances, this can be determined dynamically or set statically. The worker_connections directive sets the maximum number of simultaneous connections that each worker process can handle. The total number of connections is limited by the system’s file descriptor limit.

On an OVH server, you can check CPU cores with:

grep -c processor /proc/cpuinfo

A typical Nginx configuration snippet for performance:

user www-data;
worker_processes auto; # Or set to the number of CPU cores
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 1024; # Adjust based on system limits and expected load
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off; # Important for security

    # ... other http configurations ...
}

Gzip Compression and Caching

Enabling Gzip compression significantly reduces bandwidth usage and improves load times. Browser caching can be leveraged by setting appropriate Cache-Control headers.

http {
    # ... other http configurations ...

    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;

    # Caching for static assets
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public";
    }

    # ... server blocks ...
}

Proxying to Gunicorn/PHP-FPM

When proxying to Gunicorn (for Python/C++ extensions) or PHP-FPM, configure timeouts and buffer sizes appropriately. For C++ applications served via Gunicorn, ensure the WSGI server is tuned as well.

server {
    listen 80;
    server_name your_domain.com;

    location / {
        proxy_pass http://unix:/path/to/your/app.sock; # Or http://127.0.0.1:8000;
        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;

        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }

    # For PHP-FPM
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # Adjust PHP version
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_read_timeout 300; # Increase timeout for potentially long-running PHP scripts
    }
}

Gunicorn Tuning for C++ Extensions

Gunicorn is a popular WSGI HTTP Server for Python. When your C++ code is integrated via Python extensions (e.g., using Cython or pybind11), Gunicorn’s performance directly impacts your application’s responsiveness. Tuning involves adjusting worker types, worker counts, and timeouts.

Worker Types and Count

Gunicorn offers several worker types. For I/O-bound applications or those with significant C++ extensions that might block, the gevent or event (async) workers are often preferred over the default sync workers. The number of workers is typically set to (2 * number_of_cores) + 1, but this can be adjusted based on memory usage and the nature of your C++ extensions.

Starting Gunicorn with optimized settings:

gunicorn --workers 3 \
         --worker-class gevent \
         --bind unix:/path/to/your/app.sock \
         --timeout 120 \
         --graceful-timeout 120 \
         your_module:your_app

Explanation of parameters:

  • --workers: Number of worker processes.
  • --worker-class: The type of worker. gevent is good for I/O concurrency.
  • --bind: The address to bind to. A Unix socket is generally faster than TCP/IP for local communication.
  • --timeout: Maximum time in seconds that a worker can spend on a request. Crucial for long-running C++ computations.
  • --graceful-timeout: Timeout for graceful worker restarts.

Asynchronous Workers (Gevent/Event)

If your C++ extensions perform blocking I/O or long computations, using gevent or event workers can prevent a single slow request from blocking other requests. This requires your C++ code (or the Python wrappers) to be compatible with asynchronous I/O patterns if possible, though even for CPU-bound tasks, better concurrency management can be achieved.

Ensure you have gevent installed:

pip install gevent

PHP-FPM Tuning for C++ Integration

If your C++ code is exposed via PHP extensions (e.g., using SWIG or custom PHP extensions), tuning PHP-FPM is essential. The focus is on process management, memory limits, and execution timeouts.

Process Management

PHP-FPM uses a pool of worker processes. The pm (process manager) setting determines how these processes are managed. dynamic is often a good balance, but ondemand can save resources if traffic is sporadic. For consistently high traffic, static might offer the best performance by keeping processes ready.

Locate your PHP-FPM pool configuration file (e.g., /etc/php/7.4/fpm/pool.d/www.conf) and adjust:

; Choose one of: static, dynamic, ondemand
pm = dynamic

; If pm = dynamic:
pm.max_children = 35
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

; If pm = static:
; pm.max_children = 50

; If pm = ondemand:
; pm.max_children = 5
; pm.process_idle_timeout = 10s

; Maximum amount of memory a script may consume (e.g. 256MB)
; Crucial if your C++ extensions are memory-intensive.
memory_limit = 512M

; Maximum execution time of each script, in seconds
; Set this high enough for your C++ computations.
max_execution_time = 300

; Maximum input variables (used for POST data, etc.)
max_input_vars = 2000

Tuning `max_execution_time` and `memory_limit`

The max_execution_time directive in php.ini (and mirrored in FPM pool config) is critical. If your C++ computations take longer than the default 30 seconds, you’ll hit timeouts. Similarly, memory_limit must be sufficient for your C++ code’s memory footprint.

You can also set these per-request using ini_set() in your PHP code, but it’s better to configure them globally for consistency.

<?php
// Example of setting ini values in PHP (less preferred for global settings)
ini_set('max_execution_time', 600); // 10 minutes
ini_set('memory_limit', '1024M');

// Your C++ extension calls here...
?>

MySQL Tuning for High Load

Database performance is often a bottleneck. Tuning MySQL involves optimizing the buffer pool, query cache (though often disabled in modern versions), connection handling, and query execution.

InnoDB Buffer Pool

The innodb_buffer_pool_size is arguably the most important setting for InnoDB. It caches data and indexes. A common recommendation is to set it to 50-70% of your available RAM on a dedicated database server. On a shared OVH instance, you’ll need to be more conservative.

Edit your MySQL configuration file (e.g., /etc/mysql/mysql.conf.d/mysqld.cnf or my.cnf):

[mysqld]
# General settings
user                    = mysql
pid-file                = /var/run/mysqld/mysqld.pid
socket                  = /var/run/mysqld/mysqld.sock
datadir                 = /var/lib/mysql
log-error               = /var/log/mysql/error.log
# General log disabled for performance, enable for debugging
# general_log_file        = /var/log/mysql/mysql.log
# general_log             = 1

# InnoDB settings
innodb_buffer_pool_size = 2G  # Adjust based on available RAM (e.g., 2GB for a 4GB RAM server)
innodb_log_file_size    = 512M # Larger log files can improve write performance
innodb_flush_log_at_trx_commit = 1 # Default is 1, 0 or 2 can be faster but riskier
innodb_flush_method     = O_DIRECT # Often beneficial on Linux

# Connection settings
max_connections         = 200 # Adjust based on application needs and server capacity
thread_cache_size       = 16  # Cache threads for reuse

# Query Cache (often disabled in MySQL 8+)
# query_cache_type        = 0
# query_cache_size        = 0

# Other performance tweaks
tmp_table_size          = 64M
max_heap_table_size     = 64M
sort_buffer_size        = 4M
join_buffer_size        = 4M
read_rnd_buffer_size    = 2M
read_buffer_size        = 2M

Connection Handling and Threading

max_connections should be set to accommodate your application’s peak load. thread_cache_size helps reduce the overhead of creating new threads for each connection.

Query Optimization and Slow Query Log

Regularly analyze your slow query log to identify and optimize inefficient queries. Ensure your C++ application (or its database access layer) uses proper indexing.

[mysqld]
# ... other settings ...
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 # Log queries that don't use indexes

After making changes to my.cnf or related files, restart MySQL:

sudo systemctl restart mysql

Monitoring and Diagnostics

Effective monitoring is key to identifying performance issues before they impact users. Use tools like htop, iotop, netstat, Nginx’s status module, Gunicorn’s metrics, and MySQL’s performance schema.

System-Level Monitoring

htop provides a real-time view of CPU and memory usage per process. iotop shows disk I/O activity.

# Install if not present
sudo apt update && sudo apt install htop iotop -y

# Run them
htop
sudo iotop

Nginx Status Module

Enable Nginx’s stub_status module to get basic connection and request statistics.

# In your nginx.conf or a site-specific conf
http {
    # ...
    server {
        listen 80;
        server_name status.your_domain.com;

        location /nginx_status {
            stub_status;
            allow 127.0.0.1; # Restrict access
            deny all;
        }
    }
    # ...
}

Then reload Nginx:

sudo systemctl reload nginx

Accessing http://status.your_domain.com/nginx_status will show:

Active connections: 123
server accepts handled requests
 1604686 1604686 1356789
Reading: 6 Writing: 117 Timed out: 0 (0 requests/sec)

Gunicorn and PHP-FPM Monitoring

Gunicorn can be configured to log worker PIDs and request times. PHP-FPM provides status pages or can be monitored via pm.status_path in its pool configuration.

MySQL Performance Schema

The Performance Schema provides detailed instrumentation for MySQL. It can be used to diagnose bottlenecks at a very granular level.

-- Enable Performance Schema (if not already enabled in my.cnf)
SET GLOBAL performance_schema = ON;

-- Example: View top wait events
SELECT *
FROM performance_schema.events_waits_summary_global_by_event_name
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;

-- Example: View top queries by execution time
SELECT *
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;

By systematically tuning Nginx, your application server (Gunicorn/PHP-FPM), and the database (MySQL), you can build a highly performant and scalable infrastructure on OVH for your C++-powered applications.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Disaster Recovery 101: Architecting Auto-Failovers for Redis and PHP Deployments on OVH
  • How We Audited a High-Traffic WooCommerce Enterprise Stack on Google Cloud and Mitigated Race conditions during high-concurrency payment processing
  • Disaster Recovery 101: Architecting Auto-Failovers for Elasticsearch and Magento 2 Deployments on DigitalOcean
  • An Auditor’s Checklist for Securing WordPress Backends on OVH
  • Step-by-Step: Diagnosing Perl script high CPU throttling due to unoptimized regular expressions on AWS Servers

Copyright © 2026 · Vinay Vengala