Question

App Platform + Nginx + php-fpm issue, request hangs

I created a web service resource on App Platform, it’s built from a custom Dockerfile. The App works well (most of the time) but sometimes (randomly), requesting same API endpoint hangs and take a lot of time to complete. The same docker container doesn’t have this issue running locally, I think this problem i related with the App platform Load Balancer and some nginx configuration. Are there any particular configuration to made if work? Thanks

These are my configs:

/etc/nginx/nginx.conf:

# user www-data;
pid /tmp/nginx.pid;
worker_processes 1;

events {
    worker_connections 1024;
}

http {
    charset utf-8;

    # copies data between one FD and other from within the kernel
    # faster than read() + write()
    sendfile on;

    # send headers in one piece, it is better than sending them one by one
    tcp_nopush on;

    # don't buffer data sent, good for small data bursts in real time
    tcp_nodelay on;

    # allow the server to close connection on non responding client, this will free up memory
    reset_timedout_connection on;

    # hide server info for security
    server_tokens off;

    log_not_found off;
    types_hash_max_size 2048;

    client_body_buffer_size 16K;
    client_header_buffer_size 4k;
    client_max_body_size 20M;
    large_client_header_buffers 4 16k;

    client_body_timeout 12;
    client_header_timeout 12;
    keepalive_timeout 15;
    send_timeout 10;

    # cache information about FDs, frequently accessed files
    open_file_cache max=200000 inactive=20s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 5;
    open_file_cache_errors off;

    # MIME
    include mime.types;
    default_type application/octet-stream;

    # enhancment
    # Replace loadbalancer IP(real-ip) with actual client IP.
    set_real_ip_from  0.0.0.0/0;
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;

    # load configs
    include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/app.conf:

server {
    listen 8080;
    server_name app;
    root /var/www/html/public;

    autoindex on;
    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php-fpm.sock;
    }

    # nginx status page
    location /status-nginx {
        stub_status on;
        access_log  off;
    }

    # fpm status page and ping page
    location ~ ^/(status|ping)$ {
        access_log off;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}

/usr/local/etc/php-fpm.d/www.conf:

[www]
user = www-data
group = www-data
listen = /var/run/php-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = ondemand
pm.max_children = 9
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.process_idle_timeout = 60s
pm.max_requests = 5
request_terminate_timeout = 60s
request_slowlog_timeout = 30s
ping.path = /ping
pm.status_path = /status
slowlog = /proc/self/fd/2
catch_workers_output = yes

Submit an answer


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

I had the same problem with my PHP app on App Platform. I tried everything.

I had 2 issues going on. First it was Redis. There is a bug with TLS1.3 in the PHP Redis extension. using tlsv1.2:// helped but I also rolled out stunnel. This was super helpful here: https://github.com/phpredis/phpredis/issues/1726

The other issue ended up being related to DO’s older gVisor infrastructure. After alot of back and forth with DO via a support ticket, they migrated my app to some of their newer App Platform infrastructure with a newer gVisor version and it’s fixed my random hangs completely.

It took a LONG time to narrow this down and fix!!

Hope this helps!

Nathan

Bobby Iliev
Site Moderator
Site Moderator badge
February 8, 2024

Hey,

The configuration snippets you’ve shared are quite standard, but there are a few areas we can explore to potentially alleviate or identify the cause of the request hangs you’re experiencing.

Before diving into that, would you mind sharing why you are deploying your PHP app with a custom Dockerfile rather than the native PHP buildpack?

Regarding the Nginx configuration, here are a few suggestions:

  1. You’ve set worker_processes to 1. This is generally okay for low-traffic applications but might become a bottleneck under higher load. Consider setting this to auto, which will adjust the number of worker processes based on the number of CPU cores available.

  2. Your keepalive_timeout is set to 15 seconds. While keep-alive connections are beneficial for reducing TCP handshake overhead for multiple requests, too high a timeout can lead to connection saturation under load. Consider lowering this value if your application doesn’t rely heavily on long-lived connections, this might be especially beneficial in the context of the DigitalOcean App Platform.

Here are also some PHP-FPM config changes suggestions:

  1. You’re using the ondemand process manager with up to 9 children. This is generally efficient for memory usage but can cause delays if new child processes need to be spawned under sudden spikes of traffic. Consider switching to dynamic or static if your traffic patterns are predictable and your server has enough memory resources.

  2. The pm.max_requests value is set to 5, which is quite low. This setting controls how many requests a child process will handle before being recycled. Setting this too low can lead to unnecessary process churn, while too high a value can lead to memory leaks affecting performance. Adjust this based on your application’s stability and memory usage.

  3. Your request_terminate_timeout is set to 60s. Ensure your application’s longest-running scripts complete within this time, or consider adjusting it based on the needs of your application.

Besides that I could suggest a few more extra steps for debugging:

  • Make use of PHP-FPM’s slowlog directive to log requests that take longer than request_slowlog_timeout. This can help identify which scripts are causing delays.

  • Check the Nginx and PHP-FPM error logs for any warnings or errors that might indicate configuration issues or resource limitations.

Since you mentioned the possibility of the issue being related to the DigitalOcean Load Balancer, sudden traffic spikes or slow responses from your application can lead to queued requests, which might appear as hangs. Adding a bit of extra resources might help here.

Let me know how it goes!

Best,

Bobby

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel