加快AWS Lambda执行速度

问题描述

我正在建立一个人们可以一起玩棋盘游戏的网站。他们的动作通过一个简单的网络套接字传递,该网络套接字仅将消息中继到其他客户端。我曾经在节点中实现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秒)。

还有其他技巧或解决方案可以使我将等待时间保持在较低水平吗?

解决方法

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

DynamoDB在尝试任何读取操作时会使用RCU(读取容量单位),为了达到最终的一致性,将为2个4KB项消耗1个RCU,而对于强一致性则将消耗1个RCU。

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

要解决这个问题,人们可以构建其DynamoDB表,以按分区和可选的排序键来检索项目。相反,使用GetItem函数将仅将RCU用于返回的项目。

性能问题很可能是由于您可用的RCU总量已耗尽,您可以通过查看相关DynamoDB的读取限制来在CloudWatch中进行验证。