繁体   English   中英

当两个函数位于同一账户、同一区域时,如何从另一个 AWS Java Lambda 函数调用 aws java lambda 函数

[英]How to call an aws java lambda function from another AWS Java Lambda function when both are in same account, same region

我有一个 java aws lambda 函数或处理程序作为 AHandler 做一些事情,例如它已订阅 SNS 事件,它解析该 SNS 事件并将相关数据记录到数据库中。

我有另一个 java aws lambda BHandler,这个 BHandler 的目标是接收来自 AHandler 的请求并将响应提供给 AHandler。 因为 BHandler 的目标是提供一些 json 数据的响应。 这将被 AHandler 使用。

我可以看到任何明确的例子来说明我们如何做这些事情吗?

我看到这个例子从 java 类调用 lambda 函数和从 java 调用 lambda 函数

我的问题是关于这种情况,当一个 aws java lambda 函数(或处理程序)调用另一个 aws java lambda 函数时,两者都在同一区域、同一帐户、相同的 vpc 执行内容、相同的权利。 在这种情况下,aws java lambda 函数可以直接调用(或调用)另一个函数,或者它仍然必须提供 aws 密钥、区域等内容(如上面的链接所示)? 一个明确的例子/解释会非常有帮助。

编辑

正在调用另一个 Lambda 函数 (BHandler) 的 AHandler 存在于同一个帐户上,已经为所有内容提供了完整的AWSLambdaFullAccess ,例如

“iam:PassRole”, “lambda:*”,

这是要调用的代码:

注意:当我从普通的 java main 函数调用相同的函数时,下面的代码有效。 但它不像从 lambda 函数调用(如 ALambdaHandler 调用 BLambdaHandler 作为函数调用)。 即使它没有返回任何异常。 它只是显示超时,它被困在以下代码中: lambdaClient.invoke

String awsAccessKeyId = PropertyManager.getSetting("awsAccessKeyId");
        String awsSecretAccessKey = PropertyManager.getSetting("awsSecretAccessKey");
        String regionName = PropertyManager.getSetting("regionName");
        String geoIPFunctionName = PropertyManager.getSetting("FunctionName");

        Region region;
        AWSCredentials credentials;
        AWSLambdaClient lambdaClient;

        credentials = new BasicAWSCredentials(awsAccessKeyId,
                awsSecretAccessKey);

        lambdaClient = (credentials == null) ? new AWSLambdaClient()
                : new AWSLambdaClient(credentials);
        region = Region.getRegion(Regions.fromName(regionName));
        lambdaClient.setRegion(region);


        String returnGeoIPDetails = null;

        try {


            InvokeRequest invokeRequest = new InvokeRequest();
            invokeRequest.setFunctionName(FunctionName);
            invokeRequest.setPayload(ipInput);


            returnDetails = byteBufferToString(
                    lambdaClient.invoke(invokeRequest).getPayload(),
                    Charset.forName("UTF-8"),logger);
        } catch (Exception e) {

            logger.log(e.getMessage());
        }

编辑我按照其他人的建议做了一切并遵循了一切。 最后我联系了AWS支持,问题与一些VPC配置的东西有关,并得到了解决。如果您遇到类似的东西,那么可能是检查安全配置,VPC的东西。

我们通过使用 com.amazonaws.services.lambda.model.InvokeRequest 实现了这一点。 这是代码示例。

public class LambdaInvokerFromCode {
     public void runWithoutPayload(String functionName) {
            runWithPayload(functionName, null);
        }

        public void runWithPayload(String functionName, String payload) {
            AWSLambdaAsyncClient client = new AWSLambdaAsyncClient();
            client.withRegion(Regions.US_EAST_1);

            InvokeRequest request = new InvokeRequest();
            request.withFunctionName(functionName).withPayload(payload);
            InvokeResult invoke = client.invoke(request);
            System.out.println("Result invoking " + functionName + ": " + invoke);
    }



    public static void main(String[] args) {
            String KeyName ="41159569322017486.json";
            String status = "success";
            String body = "{\"bucketName\":\""+DBUtils.S3BUCKET_BULKORDER+"\",\"keyName\":\""+KeyName+"\", \"status\":\""+status+"\"}";
            System.out.println(body);

            JSONObject inputjson = new JSONObject(body); 
            String bucketName = inputjson.getString("bucketName");
            String keyName = inputjson.getString("keyName");
            String Status = inputjson.getString("status");
            String destinationKeyName = keyName+"_"+status;
            LambdaInvokerFromCode obj = new LambdaInvokerFromCode();
            obj.runWithPayload(DBUtils.FILE_RENAME_HANDLER_NAME,body);
        }
}

编辑:对于这种情况,请考虑使用Step Functions

我们遇到了类似的问题,并试图收集各种实现来实现这一点。 原来它与代码无关。

几个基本规则:

  1. 确保您的 lambda 函数具有正确的策略和角色,至少: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs: : : " }, { "Effect": "Allow", "Action": [ "lambda:InvokeFunction" ], "Resource": [ " " ] } ] }
  2. 具有相同区域的功能。

  3. 无需 VPC 配置。 如果您的应用程序具有 VPC,请确保您的 lambda 函数具有适当的角色策略(请参阅 AWSLambdaVPCAccessExecutionRole)

  4. 最重要的(主要是为什么它对我们来说失败了),设置正确的超时和堆大小。 调用 Lambda 将等到被调用者完成。 2 倍被调用的 lambda 值的简单数学运算有效。 此外,这仅适用于调用另一个 java lambda 函数的 java lambda 函数。 使用 node js lambda 函数调用另一个 lambda 函数没有这个问题。

以下是一些对我们有用的实现:

  1. 使用服务接口


    import com.amazonaws.regions.Regions;
    import com.amazonaws.services.lambda.AWSLambdaAsyncClientBuilder;
    import com.amazonaws.services.lambda.invoke.LambdaInvokerFactory;
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;

    public class LambdaFunctionHandler implements RequestHandler {

        @Override
        public String handleRequest(Object input, Context context) {
            context.getLogger().log("Input: " + input);

            FineGrainedService fg = LambdaInvokerFactory.builder()
                    .lambdaClient(
                            AWSLambdaAsyncClientBuilder.standard()
                            .withRegion(Regions.US_EAST_2)
                            .build()
                    )
                    .build(FineGrainedService.class);

            context.getLogger().log("Response back from FG" + fg.getClass());

            String fgRespone = fg.callFineGrained("Call from Gateway");
            context.getLogger().log("fgRespone: " + fgRespone);

            // TODO: implement your handler
            return "Hello from Gateway Lambda!";
        }

    }


    import com.amazonaws.services.lambda.invoke.LambdaFunction;

    public interface FineGrainedService {

        @LambdaFunction(functionName="SimpleFineGrained")
        String callFineGrained(String input);
    }


  1. 使用调用程序


    import java.nio.ByteBuffer;

    import com.amazonaws.services.lambda.AWSLambdaClient;
    import com.amazonaws.services.lambda.model.InvokeRequest;
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;

    public class LambdaFunctionHandler implements RequestHandler {

        @Override
        public String handleRequest(Object input, Context context) {
            context.getLogger().log("Input: " + input);

            AWSLambdaClient lambdaClient = new AWSLambdaClient();
            try {
                InvokeRequest invokeRequest = new InvokeRequest();
                invokeRequest.setFunctionName("SimpleFineGrained");
                invokeRequest.setPayload("From gateway");

                context.getLogger().log("Before Invoke");
                ByteBuffer payload = lambdaClient.invoke(invokeRequest).getPayload();
                context.getLogger().log("After Inoke");

                context.getLogger().log(payload.toString());
                context.getLogger().log("After Payload logger");

            } catch (Exception e) {
                // TODO: handle exception
            }

            // TODO: implement your handler
            return "Hello from Lambda!";
        }

    }

AWSLambdaClient 应该从构建器创建。

您可以使用LambdaClient通过传递InvocationType.EVENT参数异步调用 Lambda。 看一个例子:

LambdaClient lambdaClient = LambdaClient.builder().build();
InvokeRequest invokeRequest = InvokeRequest.builder()
        .functionName("functionName")
        .invocationType(InvocationType.EVENT)
        .payload(SdkBytes.fromUtf8String("payload"))
        .build();
InvokeResponse response = lambdaClient.invoke(invokeRequest);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM