【问题标题】:Speeding up AWS Lambda execution加速 AWS Lambda 执行
【发布时间】:2021-01-17 12:34:04
【问题描述】:

我正在实施一个人们可以一起玩棋盘游戏的网站。他们的动作通过一个简单的 websocket 传递,该 websocket 只是将消息中继到其他客户端。我曾经在 node 中实现 websocket 并从 AWS EC 实例提供服务,但我决定尝试转向无服务器,Websocket API

我关注了this tutorial,它描述了与我几乎相同的用例。

更改为无服务器后,延迟显着增加(从

var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB();

let active_connnections = null;
const get_active_connections = async () => {
    const data = await dynamodb.scan({ TableName: process.env.TABLE_NAME }).promise();
    active_connnections = data.Items.map(id => id.id.S);
};

let endpoint = null;
const connect_endpoint = async () => {
    endpoint = new AWS.ApiGatewayManagementApi({endpoint: process.env.ENDPOINT});
};

const init = async (myConnectionId) => {
    var promisesToRun = [];
    if ((!active_connnections) || !active_connnections.includes(myConnectionId)) {
        promisesToRun.push(get_active_connections());
    }
    if (!endpoint) {
        promisesToRun.push(connect_endpoint());
    }
    await Promise.all(promisesToRun);
};

const send_message = async (connectionId, message) => {
    try {
        await endpoint.postToConnection({ ConnectionId: connectionId, Data: JSON.stringify(message)}).promise();
    } catch (e) {
        if (e.statusCode == 410) {
            await dynamodb.deleteItem({ TableName: process.env.TABLE_NAME, Key: { id: {S: connectionId } } } ).promise();
        } else {
            throw e;
        }
    }
};

exports.handler = async (event, context) => {
    await init(event.requestContext.connectionId);
    const postCalls = items.map(async (id) => send_message(id, JSON.parse(event.body)));
    await Promise.all(postCalls);

当我的 lambda 没有冷启动到可接受的水平时,这减少了延迟。但是,lambda 的销毁速度相对较快(打开连接后 1-2 秒)。

是否有任何其他技巧或不同的解决方案可以让我在较长时间内保持低延迟?

【问题讨论】:

  • items.map await init 之后的下一行...想知道items 的定义在哪里?
  • 您是否排除了 DynamoDB 交互,例如通过在您的 Lambda 中硬编码代表性 DDB 数据并简单地使用它而不是实际调用 DynamoDB?

标签: amazon-web-services websocket aws-lambda aws-serverless


【解决方案1】:

我可以看到您正在使用 DynamoDB 扫描,这肯定会影响您的应用程序的性能。

DynamoDB 在尝试任何读取操作时使用 RCU(读取容量单位),1 个 RCU 将用于 2 个 4KB 项目以实现最终一致性,或 1 个 4KB 项目具有强一致性。

请务必了解,当您执行扫描时,DynamoDB 的后端会获取表中的每个项目,然后再应用过滤器。这将消耗整个表大小的 RCU。

为了解决这个问题,人们构建了他们的 DynamoDB 表,以通过分区和可选的排序键检索项目。使用 GetItem 函数将只使用 RCU 来处理返回的项目。

性能问题可能来自您的总可用 RCU 被耗尽,您可以在 CloudWatch 中通过查看相关 DynamoDB 的读取限制来验证这一点。

【讨论】:

  • 我只在这个数据库中存储连接 ID。 Cloud watch 说扫描延迟低于 15 毫秒。
  • 嗯,接下来可能是 X 光检查:aws.amazon.com/xray。如果您能提供帮助,我建议您不要使用扫描 :)
猜你喜欢
  • 2021-11-11
  • 2022-11-28
  • 2016-10-16
  • 2018-04-11
  • 2022-01-01
  • 2020-04-10
  • 2016-05-01
  • 2020-11-25
  • 2017-09-05
相关资源
最近更新 更多