现在,如果我们要创建一个lambda函数来调用另一个函数,则可以使用AWS StepFunction。
但是现在,我需要支持在StepFunctions之前编写的生产中的代码。
因此,我需要了解其工作原理。我试图创建一个非常简单的lambda来调用另一个RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{QUERY_STRING} ^var [NC]
RewriteRule ^([^/]+)$ /link.php?id=$1 [L,QSA]
的lambda函数。
我有以下serverless.yml
AWS-SDk
这是handler.js:
service: lambdaCallLambda
provider:
name: aws
runtime: nodejs6.10
functions:
hello:
handler: handler.hello
funcOne:
handler: handler.funcOne
funcTwo:
handler: handler.funcTwo
#Must install aws-sdk. #npm install --save aws-sdk
部署'use strict';
//https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html
var Lambda = require('aws-sdk/clients/lambda');
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'hello',
input: event,
}),
};
callback(null, response);
};
module.exports.funcOne = (event, context, callback) => {
var text='';
var i = 0;
for (i = 0; i < 5; i++) {
text += "The number is " + i + "\n";
}
console.log(text);
//https://docs.aws.amazon.com/general/latest/gr/rande.html
const lambda = new Lambda({
region: 'us-east-1'
});
console.log('control 3');
/*
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#constructor-property
To invoke a Lambda function
This operation invokes a Lambda function
https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html
Payload - JSON that you want to provide to your Lambda function as input.
*/
var params = {
ClientContext: "lambdaCallLambda",
FunctionName: "lambdaCallLambda-dev-funcOne",
InvocationType: "Event",
LogType: "Tail",
Payload: '{"jsonKey2":123}',
Qualifier: "1"
};
lambda.invoke(params, function(err, data) {
if (err){
console.log('control error\n');
console.log(err, err.stack); // an error occurred
}
else{
console.log('control OK\n');
console.log(data); // successful response
}
/*
data = {
FunctionError: "",
LogResult: "",
Payload: <Binary String>,
StatusCode: 123
}
*/
});
};
module.exports.funcTwo = async (event, context) => {
return 2;
//return '{"funcTwo":20000}';
//console.log("funcTwo = " + event);
};
并致电sls deploy
后,我得到以下2个输出:
本地:
funcOne
sls invoke local --function funcOne
在AWS中远程调用:
Serverless: INVOKING INVOKE
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4
control 3
control OK
{ StatusCode: 202, Payload: '' }
sls invoke --function funcOne
有人知道帽子在这里发生吗?特别是对于第一种情况,我没有任何错误。 这就是我得到的from the documentation
{
"errorMessage": "Unexpected token (",
"errorType": "SyntaxError",
"stackTrace": [
" ^",
"SyntaxError: Unexpected token (",
"createScript (vm.js:56:10)",
"Object.runInThisContext (vm.js:97:10)",
"Module._compile (module.js:542:28)",
"Object.Module._extensions..js (module.js:579:10)",
"Module.load (module.js:487:32)",
"tryModuleLoad (module.js:446:12)",
"Function.Module._load (module.js:438:3)",
"Module.require (module.js:497:17)",
"require (internal/module.js:20:19)"
]
}
Error --------------------------------------------------
Invoked function failed
For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
Your Environment Information -----------------------------
OS: linux
Node Version: 8.11.3
Serverless Version: 1.29.2
在EduardoDíaz建议之后- 我将lambda.invoke更改为:
Parameters:
err (Error) — the error object returned from the request. Set to null if the request is successful.
data (Object) — the de-serialized data returned from the request. Set to null if a request error occurs. The data object has the following properties:
Status — (Integer)
It will be 202 upon success.
这就是我从本地和远程获得的:
lambda.invoke({
FunctionName: 'lambdaCallLambda-dev-funcOne',
Payload: JSON.stringify(event, null, 2)
}, function(error, data) {
if (error) {
console.log('control ErrorFoncOne\n');
context.done('error', error);
}
if(data.Payload){
console.log('control SuccessFoncOne\n');
context.succeed(data)
}
});
这是一个SyntaxError。某处有一个“(”。 我发现了另一个开发者,发生了相同的错误here。
CloudWatch中没有错误日志
答案 0 :(得分:0)
尝试在有效负载中发送事件:
public class Program
{
public static async Task Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
Console.WriteLine(services.GetService<IConfiguration>().GetConnectionString("DefaultConnection"));
try
{
var context = services.GetRequiredService<PdContext>();
var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
var dbInitializerLogger = services.GetRequiredService<ILogger<DbInitializer>>();
await DbInitializer.Initialize(context, userManager, roleManager, dbInitializerLogger);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while migrating the database.");
}
}
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
答案 1 :(得分:0)
我强烈怀疑此问题根源于您对funcTwo
的处理程序签名:
module.exports.funcTwo = async (event, context) => {
NodeJS 6.10不支持async
/ await
。无论出于何种原因,Node总是抱怨async
令牌之后的令牌 。如果您不使用粗箭头功能:
module.exports.funcTwo = async function(event, context) {
节点将抱怨:Unexpected token function
。
选项
async
关键字。 serverless-webpack
)将功能转换为ES6(或更低版本)。 注意:如果您坚持使用6.10运行时,我想您应该做类似context.succeed(2);
或callback(null, 2);
而不是return 2;
的事情。只需使用return
语句确实即可在8.10上运行。
答案 2 :(得分:0)
我发现了问题。我们需要lamdda.invoke方法中的播放负载中的JSON.stringfy
。不需要额外的参数。根据文档,只有JSON。
lambda.invoke({
FunctionName: 'lambdaCallLambda-dev-funcTwo',
Payload: JSON.stringify({"jsonKey2":i})
...
在AWS documentation for playload中,我们有:
Payload
JSON that you want to provide to your Lambda function as input.
功能前面的异步
lambda.invoke({
FunctionName: 'lambdaCallLambda-dev-funcTwo',
Payload: JSON.stringify({"jsonKey2":i})
}, async function(error, data) { ...
和
module.exports.funcTwo = async(event, context, callback) => { ...
给我这个输出:
Loop nb=1
Loop nb=2
Loop nb=3
Loop nb=4
Loop nb=5
{"message":"hello from funcTwo","event":{"jsonKey2":3}}
{"message":"hello from funcTwo","event":{"jsonKey2":2}}
{"message":"hello from funcTwo","event":{"jsonKey2":1}}
{"message":"hello from funcTwo","event":{"jsonKey2":5}}
{"message":"hello from funcTwo","event":{"jsonKey2":4}}
虽然缺少 async 可以给我:
Loop nb=1
Loop nb=2
Loop nb=3
Loop nb=4
Loop nb=5
{"message":"hello from funcTwo","event":{"jsonKey2":1}}
{"message":"hello from funcTwo","event":{"jsonKey2":2}}
{"message":"hello from funcTwo","event":{"jsonKey2":3}}
{"message":"hello from funcTwo","event":{"jsonKey2":4}}
{"message":"hello from funcTwo","event":{"jsonKey2":5}}
我将共享handle.js
代码,以防万一其他人需要它:
'use strict';
//https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html
var Lambda = require('aws-sdk/clients/lambda');
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'hello',
input: event,
}),
};
callback(null, response);
};
/*
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#constructor-property
To invoke a Lambda function
This operation invokes a Lambda function
https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html
Payload - JSON that you want to provide to your Lambda function as input.
Serverless Framework: Lambdas Invoking Lambdas
https://lorenstewart.me/2017/10/02/serverless-framework-lambdas-invoking-lambdas/
How to escape async/await hell
https://medium.freecodecamp.org/avoiding-the-async-await-hell-c77a0fb71c4c
Iterating a Loop Using Lambda
https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-create-iterate-pattern-section.html
AWS Lambda “Process exited before completing request”
https://stackoverflow.com/questions/31627950/aws-lambda-process-exited-before-completing-request
Class: AWS.Lambda
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#constructor-property
Invoke
https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax
Programming Model(Node.js)
https://docs.aws.amazon.com/lambda/latest/dg/programming-model.html
AWS Lambda Examples
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/lambda-examples.html
*/
//The event is a file inserted in S3. This function funcOne reads the file and loop trough all quantities of products.
//Invoking a lamda function funcTwo for each process in the loop.
module.exports.funcOne = (event, context, callback) => {
//https://docs.aws.amazon.com/general/latest/gr/rande.html
const lambda = new Lambda({
region: 'us-east-1'
});
//Loop
//nbProducts = loop trough the products JSON list in S3
var nbProducts=5;
for (let i = 1; i <= nbProducts; i++) {
console.log('Loop nb='+i+'\n');
lambda.invoke({
FunctionName: 'lambdaCallLambda-dev-funcTwo',
Payload: JSON.stringify({"jsonKey2":i})
}, async function(error, data) {
if (error) {
//console.log('control ErrorFoncOne\n');
context.done('error', error);
}
if(data.Payload){
//console.log('control SuccessFoncOne\n');
console.log(data.Payload);
//context.succeed(data)
}
});
}
};
module.exports.funcTwo = async(event, context, callback) => {
callback(null, { message: 'hello from funcTwo', event });
};