如何在另一个AWS Java Lambda函数中调用aws java lambda函数,当它们位于同一帐户,同一区域时

时间:2016-04-07 17:16:44

标签: java amazon-web-services aws-lambda

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

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

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

我看到了这个示例call lambda function from a java classInvoke lambda function from java

我的问题讨论了这种情况,当一个aws java lambda函数(或处理程序)调用另一个aws java lambda函数时,它们都在同一个区域,相同的帐户,相同的vpc执行内容,相同的权限。在那种情况下,aws java lambda函数可以直接调用(或调用)到另一个或者它还必须提供aws键,区域等东西(如上面的链接)?一个明确的例子/解释将非常有用。

修改

正在调用另一个Lambda函数(BHandler)的AHandler存在于同一个帐户中,已经完成了所有内容的完整 AWSLambdaFullAccess

“IAM:PassRole”, “拉姆达:*”,

以下是要调用的代码:

注意:当我使用普通的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的东西。

4 个答案:

答案 0 :(得分:7)

我们通过使用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);
        }
}

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

几条基本规则:

  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将等到被调用的一个完成。简单数学2x被称为lambda值的工作原理。这也只是使用java lambda函数调用另一个java lambda函数。使用节点js lambda函数调用另一个lambda函数没有这个问题。

  5. 以下是一些适用于我们的实现:

    1. 使用服务界面
    2. 
      
          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. 使用调用程序
      2. 
        
            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。

答案 3 :(得分:0)

您可以使用 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);