GCP Cloud Run returns "Faithfully yours, nginx"

Viewed 282

I'm trying to host my laravel application in GCP cloud run and everything works just fine but for some reason whenever I run a POST request with lots of data (100+ rows of data - 64Mb) saving to the database, it always throw an error. I'm using nginx with docker by the way. Please see the details below.

ERROR

Cloud Run Logs

The request has been terminated because it has reached the maximum request timeout.

nginx.conf

worker_processes  1;

events {
    worker_connections  1024;
}
http {
    include       mime.types;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen LISTEN_PORT default_server;
        server_name _;
        root /app/public;
        index index.php;
        charset utf-8;
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        location = /favicon.ico { access_log off; log_not_found off; }
        location = /robots.txt  { access_log off; log_not_found off; }
        access_log /dev/stdout;
        error_log /dev/stderr;
        sendfile off;
        client_max_body_size 100m;

        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_intercept_errors off;
            fastcgi_buffer_size 32k;
            fastcgi_buffers 8 32k;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }
    #include /etc/nginx/sites-enabled/*;
}

daemon off;

Dockerfile

FROM php:8.0-fpm-alpine

RUN apk add --no-cache nginx wget

RUN docker-php-ext-install mysqli pdo pdo_mysql

RUN mkdir -p /run/nginx

COPY docker/nginx.conf /etc/nginx/nginx.conf

RUN mkdir -p /app
COPY . /app

RUN sh -c "wget http://getcomposer.org/composer.phar && chmod a+x composer.phar && mv composer.phar /usr/local/bin/composer"
RUN cd /app && \
    /usr/local/bin/composer install --no-dev

RUN chown -R www-data: /app

CMD sh /app/docker/startup.sh

Laravel version:

v9


Please let me know if you need some data that is not indicated yet on my post.

3 Answers

I think the issue has nothing to do with php, laravel, or nginx, but with Cloud Run.

As you can see in the Google Cloud documentation when they describe HTTP 504: Gateway timeout errors:

HTTP 504
The request has been terminated because it has reached the maximum request 
timeout.

If your service is processing long requests, you can increase the request timeout. If your service doesn't return a response within the time specified, the request ends and the service returns an HTTP 504 error, as documented in the container runtime contract.

As suggested in the docs, please, try increasing the request timeout until your application can process the huge POST data you mentioned: it is set by default to 5 minutes, but can be extended up to 60 minutes.

As described in the docs, you can set it through the Google Cloud console and the gcloud CLI; directly, or by modifying the service YAML configuration.

Default Nginx timeout is 60s. Since you have mentioned the data is 64mb. It will take time to process that request in your backend and send back the response within 60s.

So either you could try to increase the nginx timeout by adding the below block in your nginx.conf file

http{
   ...
   proxy_read_timeout 300;
   proxy_connect_timeout 300;
   proxy_send_timeout 300;
   keepalive_timeout 3000;
   ...
}

Or better way would be, dont process the data immediately, push the data to a message queue and send the response instantly.let the background workers handle the process with data. I dont know much about laravel. In django we can use rabbitmq and celery/ pika.

To get the result for the request with huge data you can poll the server at regular interval or setup a websocket connection

Increase max_execution_time in php configuration. By default it is only 30 seconds. Make 30 minutes for example:

max_execution_time = 1800

Increase timeouts of nginx:

http{
   ...
   proxy_read_timeout 1800;
   proxy_connect_timeout 1800;
   proxy_send_timeout 1800;
   send_timeout 1800;
   keepalive_timeout 1800;
   ...
}

Another idea for investigation is to give more resources to your cloud instance (more CPUs, more RAM) in order to process your request faster and avoid timeout. But eventually it should be increased.

Related