Приложение NodeJs для Amazon ELB выдает 502

У нас есть приложение узла, работающее за Amazon Elastic Load Balancer (ELB), которое случайным образом выдает ошибку 502 при наличии нескольких одновременных запросов и когда для обработки каждого запроса требуется время. Изначально мы пытались увеличить время простоя ELB до 5 минут, но все равно получали 502 ответа.

Когда мы связались с командой Amazon, они сказали, что это происходит из-за того, что серверная часть закрывает соединение с ELB через 5 секунд.

ELB будет отправлять HTTP-502 обратно вашим клиентам по следующим причинам:

  • Балансировщик нагрузки получил TCP RST от цели при попытке установить соединение.
  • Цель закрыла соединение с TCP RST или TCP FIN, в то время как у балансировщика нагрузки был невыполненный запрос к цели.
  • Целевой ответ имеет неверный формат или содержит недопустимые заголовки HTTP.
  • Была использована новая целевая группа, но ни одна из целей еще не прошла первоначальную проверку работоспособности. Цель должна пройти одну проверку здоровья, чтобы считаться здоровой.

Мы попытались установить время ожидания/время ожидания нашего приложения больше, чем время простоя ELB (5 минут), чтобы ELB мог отвечать за открытие и закрытие соединений. Но все же мы сталкиваемся с ошибкой 502.

js:

var http = require( 'http' );
var express = require( 'express' );
var url = require('url');
var timeout = require('connect-timeout')

const app = express();

app.get( '/health', (req, res, next) => {
  res.send( "healthy" );
});

app.get( '/api/test', (req, res, next) => {
  var query = url.parse( req.url, true ).query;
  var wait = query.wait ? parseInt(query.wait) : 1;
  setTimeout(function() {
    res.send( "Hello!" );
  }, wait );
});

var server = http.createServer(app);
server.setTimeout(10*60*1000); // 10 * 60 seconds * 1000 msecs
server.listen(80, function () {
  console.log('**** STARTING SERVER ****');
});

person RAGHU RAMAN    schedule 11.08.2017    source источник
comment
Это может быть вам интересно: github.com/hapijs/hapi/issues/3738 #issuecomment-364213653   -  person Matt Harrison    schedule 09.02.2018


Ответы (3)


Попробуйте установить server.keepAliveTimeout на что-то другое, кроме 5s по умолчанию. См.: https://nodejs.org/api/http.html#http_server_keepalivetimeout. Согласно документам AWS, вы бы хотели, чтобы это значение было больше, чем тайм-аут простоя балансировщика нагрузки.

Примечание: это было добавлено в Node v8.0.0.

Кроме того, если вы все еще используете классический ELB, рассмотрите возможность перехода на новый Application Load Balancer, поскольку, исходя из текущего опыта, это, похоже, значительно улучшило нашу ситуацию. Вы также сэкономите несколько долларов, если у вас будет много отдельных ELB для каждой службы. Недостатком может быть то, что для всех ваших служб существует 1 точка отказа. Но в AWS мы верим :)

person dandoen    schedule 27.12.2017
comment
@raghu-raman, пожалуйста, примите этот ответ, если это решило вашу проблему. - person dandoen; 27.11.2019

В моем случае мне нужно было обновить версию nodejs:

https://github.com/nodejs/node/issues/27363

После этого проблема была устранена.

person Marcelo Aguiar    schedule 02.09.2019
comment
Добро пожаловать в СЕ! Можете ли вы немного рассказать, почему это было решением этой проблемы? - person Dux; 02.09.2019
comment
Судя по ссылке, более новые версии узла предлагают параметр headersTimout, который по умолчанию равен 40 с. Если вы запускаете версию узла, которая поддерживает настройку этого headersTimeout, но вы его не установили, вам необходимо убедиться, что время ожидания вашего балансировщика нагрузки и параметр keepAliveTimeout вашего сервера узла должны быть ниже 40 с. Таким образом, ELB может иметь тайм-аут, установленный на 35 с, и keepAliveTimeout может быть установлен на 36 с, а значение headersTimeout по умолчанию, равное 40 с, должно быть в порядке. Или вы можете установить для headersTimeout значение выше, чем значение keepAliveTimeout. - person wottle; 20.12.2019
comment
TL;DR для этой проблемы находится в выше, а также здесь. - person ab77; 03.01.2020

Измените свой server.listen() на это:

const port = process.env.PORT || 3000;
const server = app.listen(port, function() {
  console.log("Server running at http://127.0.0.1:" + port + "/");
});

Подробнее об этом можно прочитать здесь.

person Matthis Kohli    schedule 21.04.2019
comment
Как это исправить 502s? Документы, на которые вы ссылаетесь, предназначены для Elastic Beanstalk, о которых ОП никогда не упоминал. - person Hurricane Hamilton; 02.09.2020