#amazon-web-services #websocket #aws-api-gateway
#amazon-веб-сервисы #веб-сокет #aws-api-gateway
Вопрос:
Мы столкнулись с ошибкой при выполнении postToConnection()
вызова SDK в качестве обещания, полная информация об ошибке приведена ниже. Другие вызовы в той же функции с другим идентификатором соединения выполняются успешно. Ожидаемые 410 ошибок подключения происходят правильно и в миллисекундах и обрабатываются корректно.
Для возврата этой ошибки требуется от 40 секунд до более минуты, что приводит к тому, что она всегда вызывает ошибки «тайм-аут запроса конечной точки» в API веб-сокетов, поскольку максимальный тайм-аут запроса составляет 30 секунд. Кто-нибудь сталкивался с этой проблемой раньше и / или какое-либо реализованное решение? Любые идеи по устранению проблемы будут высоко оценены, спасибо.
Неизвестная ошибка: сетевая ошибка связи с конечной точкой в Object.extractError (/opt/nodejs/node_modules/aws-sdk/lib/protocol/json.js:51:27)
Ответ №1:
вы пытаетесь использовать postToConnection внутри обработчика подключения? Соединение с веб-сокетом создается только после того, как обработчик соединения вернул код состояния 200. Вы не должны использовать postToConnection внутри обработчика подключения.
Комментарии:
1. Спасибо за приведенное выше предложение, теперь оно работает так, как ожидалось!
2. как отправить сообщение клиенту, который только что подключился? 🙂
3. @patrick Похоже, что клиент должен отправить первоначальный запрос на отдельный маршрут, чтобы получить первое сообщение.
Ответ №2:
Чтобы избежать головной боли 410 при использовании веб-сокетов без сервера, не забывайте перехватывать исключения:
export const ApiGatewayConnector = (event) => {
const endpoint = process.env.IS_OFFLINE
? 'http://localhost:3001'
: `${event.requestContext.domainName}/${event.requestContext.stage}`
const apiVersion = '2018-11-29'
return new AWS.ApiGatewayManagementApi({ apiVersion, endpoint })
}
….
if (event.requestContext.stage == 'local') {
await ApiGatewayConnector(event)
.postToConnection({ ConnectionId, Data })
.promise()
.catch(_ => removeId(ConnectionId));<----- N.B. Remove disconnected IDs
} else {
await ws.send(Data, ConnectionId)
}
}
Ответ №3:
Эта ошибка выдается при вызове .postToConnection в ответ на событие $connect . Вы можете вызвать .postConnection без ошибок в ответ на событие $default .
// index.js
// the handler is defined as: index.handler
const AWS = require("aws-sdk");
exports.handler = function (event, context, callback) {
console.log('event.requestContext.eventType', event amp;amp; event.requestContext amp;amp; event.requestContext.eventType)
if (event.requestContext.eventType === "CONNECT") {
console.log('$connect event')
// calling apigwManagementApi.postToConnection will throw an exception
callback(null, {
statusCode: 200,
body: "Connected"
});
} else if (event.requestContext.eventType === "DISCONNECT") {
console.log('$disconnect event')
// calling apigwManagementApi.postToConnection is pointless since the client has disconneted
callback(null, {
statusCode: 200,
body: "Disconnected"
});
} else {
console.log('$default event')
const ConnectionId = event.requestContext.connectionId
const bodyString = event.body
const Data = bodyString
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: "2018-11-29",
endpoint: event.requestContext.domainName "/" event.requestContext.stage
});
apigwManagementApi
.postToConnection({ ConnectionId, Data })
.promise().then(() => {
callback(null, {
statusCode: 200,
body: "Disconnected"
});
})
}
};
Ответ №4:
Не совсем уверен, соответствует ли это наилучшей практике, но я смог использовать postToConnection
внутри connect
обработчика (вызвав callback
перед инициализацией postToConnection
)
exports.handler = async (event, context, callback) => {
try {
const {
body = '{}',
requestContext: { apiId, connectionId, routeKey, stage },
} = event;
const apigwManagementApi = new ApiGatewayManagementApi({
endpoint: 'local' === stage ? `http://localhost:4002` : `https://${apiId}.execute-api.${process.env.AWS_REGION}.amazonaws.com/${stage}`,
});
switch(routeKey) {
case '$connect':
// call callback to create connection
callback(null, {
statusCode: 200,
body: "Connected"
});
await apigwManagementApi.postToConnection({
ConnectionId: connectionId,
Data: JSON.stringify({
action: 'test-message'
}),
}).promise();
break;
case '$disconnect':
console.log('DISCONNECT');
break;
default:
console.log('DEFAULT');
break;
}
return { statusCode: 200 };
} catch (error) {
console.log('Got error', error)
}
};
Комментарии:
1. Я пробовал это, но это просто не сработало для меня