gpt4 book ai didi

concurrency - Lambda SQL Server RDS 连接泄漏

转载 作者:行者123 更新时间:2023-12-03 23:45:05 28 4
gpt4 key购买 nike

问题
我正在使用 mssql频繁调用的 Lambda 中的 v6.2.0(在标准负载下持续约 25 个并发调用)。
我似乎在连接池或其他方面遇到了问题,因为我一直有大量打开的数据库连接,这些连接使我的数据库(RDS 上的 SQL Server)不堪重负,导致 Lambda 超时等待查询结果。
我已经阅读了文档、各种类似问题、Github 问题等,但对于这个特定问题没有任何效果。
我已经学到的东西

  • 我确实了解到,由于处理程序函数之外的变量在同一容器中的调用之间共享,因此可以跨调用进行池化。这让我觉得我应该只看到运行我的 Lambda 的每个容器的几个连接,但我不知道有多少,所以很难验证。最重要的是,池化应该让我远离成吨的开放连接,所以有些事情不能正常工作。
  • 有几种不同的使用方式 mssql我已经尝试了其中的几个。值得注意的是,我尝试使用大值和小值指定最大池大小,但得到了相同的结果。
  • AWS 建议您在尝试创建新池之前先检查是否已有池。我试过没有用。有点像 pool = pool || await createPool()
  • 我知道 RDS Proxy 的存在是为了帮助解决此类情况,但似乎(目前)没有为 SQL Server 实例提供它。
  • 我确实有能力稍微减慢我的数据速度,但这对整个产品的性能有轻微影响,所以我不想这样做只是为了避免解决数据库连接问题。
  • 如果不加检查,我一次看到多达 700 个连接到数据库,这让我认为存在某种泄漏,这可能不仅仅是高使用率的合理结果。
  • 我没有找到按照 re:Invent 幻灯片的建议缩短 SQL Server 端连接 TTL 的方法。也许这是答案的一部分?
    enter image description here

  • 代码
    'use strict';

    /* Dependencies */
    const sql = require('mssql');
    const fs = require('fs').promises;
    const path = require('path');
    const AWS = require('aws-sdk');
    const GeoJSON = require('geojson');

    AWS.config.update({ region: 'us-east-1' });
    var iotdata = new AWS.IotData({ endpoint: process.env['IotEndpoint'] });

    /* Export */

    exports.handler = async function (event) {

    let myVal= event.Records[0].Sns.Message;

    // Gather prerequisites in parallel
    let [
    query1,
    query2,
    pool
    ] = await Promise.all([
    fs.readFile(path.join(__dirname, 'query1.sql'), 'utf8'),
    fs.readFile(path.join(__dirname, 'query2.sql'), 'utf8'),
    sql.connect(process.env['connectionString'])
    ]);

    // Query DB for updated data
    let results = await pool.request()
    .input('MyCol', sql.TYPES.VarChar, myVal)
    .query(query1);

    // Prepare IoT Core message
    let params = {
    topic: `${process.env['MyTopic']}/${results.recordset[0].TopicName}`,
    payload: convertToGeoJsonString(results.recordset),
    qos: 0
    };

    // Publish results to MQTT topic
    try {
    await iotdata.publish(params).promise();
    console.log(`Successfully published update for ${myVal}`);

    //Query 2
    await pool.request()
    .input('MyCol1', sql.TYPES.Float, results.recordset[0]['Foo'])
    .input('MyCol2', sql.TYPES.Float, results.recordset[0]['Bar'])
    .input('MyCol3', sql.TYPES.VarChar, results.recordset[0]['Baz'])
    .query(query2);

    } catch (err) {
    console.log(err);
    }
    };

    /**
    * Convert query results to GeoJSON for API response
    * @param {Array|Object} data - The query results
    */
    function convertToGeoJsonString(data) {
    let result = GeoJSON.parse(data, { Point: ['Latitude', 'Longitude']});
    return JSON.stringify(result);
    }

    请帮助我理解为什么我的连接失控以及如何解决它。对于奖励积分:在 Lambda 上处理高数据库并发性的理想策略是什么?
    最终,这项服务需要处理几倍于当前负载——我意识到这会成为一个非常大的负载。我愿意接受诸如只读副本或其他读取性能提升措施之类的选项,只要它们与 SQL Server 兼容,并且它们不仅仅是编写正确的数据库访问代码的警察。
    请让我知道我是否可以改进问题。我知道那里有类似的,但我已经阅读/尝试了很多,但没有找到帮助。提前致谢!
    相关资料
  • https://forums.aws.amazon.com/thread.jspa?messageID=678029 (旧但相似)
  • https://www.slideshare.net/AmazonWebServices/best-practices-for-using-aws-lambda-with-rdsrdbms-solutions-srv320 re:Invent 幻灯片
  • https://www.jeremydaly.com/reuse-database-connections-aws-lambda/相关信息,但适用于 MySQL 而不是 SQL Server
  • 最佳答案

    回答
    经过4天的努力,我终于找到了答案。我需要做的就是扩大数据库。代码实际上很好。
    我来自 db.t2.microdb.t3.small (或 1 个 vCPU、1GB RAM 到 2 个 vCPU 和 2GB RAM),净成本约为 15 美元/月。
    理论
    就我而言,数据库可能无法同时处理我所有调用的处理(涉及多个地理计算)。我确实看到 CPU 上升,但我认为这是高开放连接的结果。当查询变慢时,并发调用会随着 Lambda 开始等待结果而堆积起来,最终导致它们超时并且无法正确关闭它们的连接。
    比较:
    db.t2.micro:

  • 200 多个 DB 连接(如果您让它运行,则会持续增加)
  • 50+ 并发调用
  • 当事情变慢时,Lambda 持续时间超过 5000 毫秒,空载时约为 300 毫秒

  • db.t3.small:
  • 25-35 个 DB 连接(持续)
  • ~5 个并发调用
  • ~33 ms Lambda 持续时间 <-- 快十倍!

  • CloudWatch 仪表板
    CloudWatch Dashboard
    概括
    我认为这个问题让我感到困惑,因为它闻起来不像是容量问题。过去几乎每次我处理高数据库连接时,都是代码错误。在那里尝试了选项后,我认为这是我需要理解的“无服务器的一些神奇问题”。最后,它就像更改数据库层一样简单。我的看法是,数据库容量问题可以通过高 CPU 和内存使用率以外的方式表现出来,而且高连接可能是代码错误之外的其他原因。
    更新(4个月内)
    这继续工作得很好。令我印象深刻的是,将 DB 资源翻倍似乎已提供 > 2 倍的性能。现在,由于负载(或开发过程中的临时错误),数据库连接变得非常高(甚至超过 1k),数据库会处理它。我根本没有看到数据库连接超时或数据库因负载而陷入困境的任何问题。从最初撰写本文开始,我添加了几个 CPU 密集型查询来支持报告工作负载,并且它继续同时处理所有这些负载。
    自撰写本文以来,我们还为一位客户将此设置部署到生产环境中,它可以毫无问题地处理该工作负载。

    关于concurrency - Lambda SQL Server RDS 连接泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63302679/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com