【发布时间】:2020-12-11 22:33:18
【问题描述】:
问题
我在频繁调用的 Lambda 中使用 mssql 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 的方法。也许这就是答案的一部分?
代码
'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 上处理高 DB 并发的理想策略是什么?
最终,该服务需要处理数倍于当前负载的负载——我意识到这将成为一个非常大的负载。我对只读副本或其他读取性能提升措施等选项持开放态度,只要它们与 SQL Server 兼容,而且它们不仅仅是为了编写正确的数据库访问代码。
如果我能改进这个问题,请告诉我。我知道那里有类似的,但我已经阅读/尝试了很多,但没有发现它们可以提供帮助。提前致谢!
相关资料
【问题讨论】:
标签: concurrency aws-lambda amazon-rds