AWS SQS + API 网关 + Lambda + 数据库
AWS SQS + API Gateway + Lambda + DB
我使用API网关+Lambda+数据库。
如果请求过多,会出现连接过多错误。
为了测试,我不想增加最大连接数选项。
是否可以使用 SQS -> Lambda -> API 网关 -> Lambda -> 数据库?
还是其他方式?
首先,确保不要在每次调用 lambda 时都创建新连接。
您应该在 lambda 处理程序之外创建连接(因此它将在初始化时创建),或者使用连接池。
这样,数据库的连接数将与并发调用数成正比。
您可以设置 lambda 的并发限制以限制活动连接(但这意味着当您达到并发限制时,触发您的 lambda 可能会因并发限制而失败)。
你可以用SQS触发你的lambda,这样,请求将在达到并发限制的情况下排队,直到之前的请求结束。
在不为 lambda 设置并发限制的情况下使用 SQS 不会解决问题,因为并发调用(=活动连接)的数量仍然会很高。
我看不出做 'SQS -> Lambda -> API Gateway -> Lambda -> DB' 之类的事情有任何好处。一个可能的用例是 'API Gateway -> SQS -> Lambda'.
您也可以只使用 'API Gateway -> Lambda' 来设置 lambda 并发限制。在这种情况下,某些对 API 网关的调用可能会失败,应使用 exponential backoff.
重试
Is it possible to use SQS -> Lambda -> API Gateway -> Lambda -> DB?
回答:是的,你可以做到,请看下面的例子
用 api getway url 替换你的电话并点击休息电话,但不是你问题的解决方案。
var https = require('https');
exports.handler = (event, context, callback) => {
var params = {
host: "bittrex.com",
path: "/api/v1.1/public/getmarketsummaries"
};
var req = https.request(params, function(res) {
let data = '';
console.log('STATUS: ' + res.statusCode);
res.setEncoding('utf8');
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
console.log("DONE");
console.log(JSON.parse(data));
});
});
req.end();
};
其他方法:
After a Lambda function is executed, AWS Lambda maintains the
Execution Context for some time in anticipation of another Lambda
function invocation. In effect, the service freezes the Execution
Context after a Lambda function completes, and thaws the context for
reuse, if AWS Lambda chooses to reuse the context when the Lambda
function is invoked again. This Execution Context reuse approach has
the following implications:
Any declarations in your Lambda function code (outside the handler
code, see Programming Model) remains initialised, providing additional
optimization when the function is invoked again. For example, if your
Lambda function establishes a database connection, instead of
reestablishing the connection, the original connection is used in
subsequent invocations. You can add logic in your code to check if a
connection already exists before creating one.
示例:
import sys
import logging
import rds_config
import pymysql
#rds settings
rds_host = "rds-instance-endpoint"
name = rds_config.db_username
password = rds_config.db_password
db_name = rds_config.db_name
logger = logging.getLogger()
logger.setLevel(logging.INFO)
try:
conn = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5)
except:
logger.error("ERROR: Unexpected error: Could not connect to MySQL instance.")
sys.exit()
logger.info("SUCCESS: Connection to RDS MySQL instance succeeded")
def handler(event, context):
"""
This function fetches content from MySQL RDS instance
"""
item_count = 0
with conn.cursor() as cur:
cur.execute("create table Employee3 ( EmpID int NOT NULL, Name varchar(255) NOT NULL, PRIMARY KEY (EmpID))")
cur.execute('insert into Employee3 (EmpID, Name) values(1, "Joe")')
cur.execute('insert into Employee3 (EmpID, Name) values(2, "Bob")')
cur.execute('insert into Employee3 (EmpID, Name) values(3, "Mary")')
conn.commit()
cur.execute("select * from Employee3")
for row in cur:
item_count += 1
logger.info(row)
#print(row)
conn.commit()
return "Added %d items from RDS MySQL table" %(item_count)
Executing pymysql.connect() outside of the handler allows your
function to re-use the database connection for better performance.
我使用API网关+Lambda+数据库。
如果请求过多,会出现连接过多错误。
为了测试,我不想增加最大连接数选项。
是否可以使用 SQS -> Lambda -> API 网关 -> Lambda -> 数据库?
还是其他方式?
首先,确保不要在每次调用 lambda 时都创建新连接。 您应该在 lambda 处理程序之外创建连接(因此它将在初始化时创建),或者使用连接池。
这样,数据库的连接数将与并发调用数成正比。
您可以设置 lambda 的并发限制以限制活动连接(但这意味着当您达到并发限制时,触发您的 lambda 可能会因并发限制而失败)。
你可以用SQS触发你的lambda,这样,请求将在达到并发限制的情况下排队,直到之前的请求结束。
在不为 lambda 设置并发限制的情况下使用 SQS 不会解决问题,因为并发调用(=活动连接)的数量仍然会很高。
我看不出做 'SQS -> Lambda -> API Gateway -> Lambda -> DB' 之类的事情有任何好处。一个可能的用例是 'API Gateway -> SQS -> Lambda'.
您也可以只使用 'API Gateway -> Lambda' 来设置 lambda 并发限制。在这种情况下,某些对 API 网关的调用可能会失败,应使用 exponential backoff.
重试Is it possible to use SQS -> Lambda -> API Gateway -> Lambda -> DB?
回答:是的,你可以做到,请看下面的例子 用 api getway url 替换你的电话并点击休息电话,但不是你问题的解决方案。
var https = require('https');
exports.handler = (event, context, callback) => {
var params = {
host: "bittrex.com",
path: "/api/v1.1/public/getmarketsummaries"
};
var req = https.request(params, function(res) {
let data = '';
console.log('STATUS: ' + res.statusCode);
res.setEncoding('utf8');
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
console.log("DONE");
console.log(JSON.parse(data));
});
});
req.end();
};
其他方法:
After a Lambda function is executed, AWS Lambda maintains the Execution Context for some time in anticipation of another Lambda function invocation. In effect, the service freezes the Execution Context after a Lambda function completes, and thaws the context for reuse, if AWS Lambda chooses to reuse the context when the Lambda function is invoked again. This Execution Context reuse approach has the following implications:
Any declarations in your Lambda function code (outside the handler code, see Programming Model) remains initialised, providing additional optimization when the function is invoked again. For example, if your Lambda function establishes a database connection, instead of reestablishing the connection, the original connection is used in subsequent invocations. You can add logic in your code to check if a connection already exists before creating one.
示例:
import sys
import logging
import rds_config
import pymysql
#rds settings
rds_host = "rds-instance-endpoint"
name = rds_config.db_username
password = rds_config.db_password
db_name = rds_config.db_name
logger = logging.getLogger()
logger.setLevel(logging.INFO)
try:
conn = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5)
except:
logger.error("ERROR: Unexpected error: Could not connect to MySQL instance.")
sys.exit()
logger.info("SUCCESS: Connection to RDS MySQL instance succeeded")
def handler(event, context):
"""
This function fetches content from MySQL RDS instance
"""
item_count = 0
with conn.cursor() as cur:
cur.execute("create table Employee3 ( EmpID int NOT NULL, Name varchar(255) NOT NULL, PRIMARY KEY (EmpID))")
cur.execute('insert into Employee3 (EmpID, Name) values(1, "Joe")')
cur.execute('insert into Employee3 (EmpID, Name) values(2, "Bob")')
cur.execute('insert into Employee3 (EmpID, Name) values(3, "Mary")')
conn.commit()
cur.execute("select * from Employee3")
for row in cur:
item_count += 1
logger.info(row)
#print(row)
conn.commit()
return "Added %d items from RDS MySQL table" %(item_count)
Executing pymysql.connect() outside of the handler allows your function to re-use the database connection for better performance.