15
votes

I am getting 504 GATEWAY_TIMEOUT http response after 60s of page loading.

It is not an actual page that is being loaded, than rather a process that is being executed. I am expecting it to take longer than 60s and I've tried to increase the timeout value, but it didn't help.

I am using express framework for routing and I host the job on EB (AWS Elastic Beanstalk). Since I have increased all timeout values that I could possibly find on EB and Load Balancers in AWS console, I assume it must be the app itself that has timeout set to 60s. However, I might be wrong.

My code:

/* GET home page. */
router.get('/main',function(req, res, next) {
req.connection.setTimeout(600000);
        mainProcess(res);
        //res.send("mainProcess() called");
    });

UPDATE:

Besides this, I've tried a different approach. I added this code to the app.js:

var connectTimeout = require('connect-timeout');
var longTimeout = connectTimeout({ time: 600000 });
app.use(longTimeout);

Didn't help either.

UPDATE2: I have also tried increasing the timeout in /bin/www like this:

var server = http.createServer(app);
server.timeout=600000;

UPDATE3: I have noticed that the timeout is related to the nginx configuration. As my logs say: upstream timed out (110: Connection timed out) while reading response header However, I can't figure out a way to edit nginx config on Elastic beanstalk. I did some research, but it all seems non standard to me and too rigid for such simple thing.

4
Try to use the connect-timeout package inside your function request arguments like this: var timeout = require('connect-timeout'); app.post('/test', timeout('6s'), function(req, res, next) {console.log('test')})Fernando Zamperin
Thank you, but I can't see where can I do that, as I have no app.post anywhere. The express framework did it differently. There is only app.use('/', routes);Ondrej Tokar
That was just an example in your first code at the answer put it before the request function like this: /* GET home page. */ var timeout = require('connect-timeout'); router.get('/main', timeout('6s'), function(req, res, next) { mainProcess(res); //res.send("mainProcess() called"); });Fernando Zamperin
Tried it, still the same issue.Ondrej Tokar
Did you check if the request is hitting nodejs? If you can access your nginx conf files e.g: location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 60s; //Here is where you put the timeout }Fernando Zamperin

4 Answers

7
votes

From your Update3 information, I think you should config your nginx configure file, like:

server {
    listen  80;
    server_name     *.*;
    location / {
            proxy_pass http://192.168.0.100:8001;
            proxy_connect_timeout 60s;
            proxy_read_timeout 5400s;
            proxy_send_timeout 5400s;
            proxy_set_header host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_redirect default;
    }
}

proxy_read_timeout and proxy_send_timeout is related to your problem.

7
votes

In your .ebextensions config file, add the following code:

container_commands:
  change_proxy_timeout:
    command: |
      sed -i '/\s*location \/ {/c \
              location / { \
                  proxy_connect_timeout       300;\
                  proxy_send_timeout          300;\
                  proxy_read_timeout          300;\
                  send_timeout                300;\
              ' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf
4
votes

Normally when a job takes more than 30 seconds or 40 seconds, I usually notify the user that is executing and then I create a process to work with the database instead of a normal request to the server to avoid the user to wait for the request and to avoid that timeout problem, you can try this for example when you set the server to listen to a specified port:

//Create server with specified port
var server = app.listen(app.get('port'), function() {
  debug('Express server listening on port ' + server.address().port);
});
//set timeout time
server.timeout = 1000;
2
votes

I had same issue so I tried to set timeout = 120000 as follows:

var server= http.createServer(app).listen(port, function()
{
    console.log("Express server listening on port " + port)
})
server.timeout = 120000;