【问题标题】:AWS Lambda Application with Java resource具有 Java 资源的 AWS Lambda 应用程序
【发布时间】:2022-01-09 22:40:06
【问题描述】:

我有一个可以在本地运行的项目,但它在 AWS 上失败了。要在本地运行项目,我先执行sam build,然后执行sam local start-api --host 0.0.0.0。然后我打电话给http://localhost:3000/skill2/task1 并得到你好世界的回应。当我调用 api 网关 https://p4x0n2nemc.execute-api.us-east-2.amazonaws.com/Prod/skill2/task1 时,它失败了。我在 cloudwatch 中看到的错误是

Class not found: helloworld.App: java.lang.ClassNotFoundException
java.lang.ClassNotFoundException: helloworld.App. Current classpath: file:/var/task/

我使用此命令创建了 helloworld 应用程序并将其复制到我的 AWS Lambda 应用程序中。

sam init --name java11-demo-app --runtime java11 --dependency-manager gradle --app-template hello-world

这里是带有 Java 资源的 AWS Lambda 应用程序的 Github 存储库

https://github.com/bennebbenneb/sample-app

如何更新此 AWS Lambda 应用程序,以便它在 NodeJS 资源之外创建 Java 资源?我不想手动压缩 Java 项目并上传它。我希望将 Java 代码构建为管道的一部分。

本地构建输出sam build

在本地主机上工作的 Java Lambda

可以从 AWS 控制台创建 AWS Lambda 应用程序。这些是 CloudFormation 项目。 https://us-east-2.console.aws.amazon.com/lambda/home?region=us-east-2#/create/application

sam build 添加到 buildspec.yml 时出错

删除Architectures 配置后出错

AWS Lambda 应用程序创建的资源

【问题讨论】:

  • 你想同时运行 java 和 node js 吗?
  • @AnandVarkeyPhilips 我试图让项目构建一个 lambda 是 NodeJS 和另一个单独的 lambda 是 Java。这在我的本地主机上工作
  • #1 你的问题解决了吗? #2 您是否尝试在 aws 上的 nodejs lambda 中执行 java 代码? #3 为什么不用纯nodejs或者纯java实现呢?
  • @JRichardsz #1 我现在更好地理解了这个问题,但还没有解决。如果没有更简单的解决方案,我计划在赏金到期之前接受下面的答案。 #2 我正在尝试从项目中创建 2 个单独的 lambda。一个 lambda 是 Java,另一个是 NodeJS。 #3 每个 lambda 只用一种语言编写。此外,没有选择预安装 Java 的 Docker 映像的选项,只有 NodeJS。我希望 AWS 允许我们在未来自定义构建映像以简化此操作

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


【解决方案1】:

buildspec.yml 如果您想使用 AWS CodeBuild 进行部署(这将是一个不寻常的流程):

---
version: '0.2'
phases:
  install:
    commands:
    - echo Entered the install phase...
    - npm install --global lerna
    - lerna bootstrap --concurrency=1 -- --production
  build:
    commands:
    - sam build
    - sam deploy --stack-name stackoverflow-stack --capabilities CAPABILITY_IAM --no-fail-on-empty-changeset
      --s3-bucket your-bucket-name-here --parameter-overrides AppId=your-app-id-here

buildspec.yml 如果您只想生成可以直接部署的 CloudFormation 模板文件(使用 CodeDeploy 或其他方式)。它和你已经拥有的几乎一样,只是有以下不同:

  • 添加sam build
  • 使用sam package 而不是aws cloudformation packagesam package 使用 .aws-sam/template.yaml(sam build 的输出)而不是 template.yaml 作为第一个默认值。
---
version: '0.2'
phases:
  install:
    commands:
    - echo Entered the install phase...
    - npm install --global lerna
    - lerna bootstrap --concurrency=1 -- --production
  build:
    commands:
    - sam build
    - sam package --s3-bucket your-bucket-name-here --output-template-file
      template-export.yml
artifacts:
  files:
  - template-export.yml

Edit2:OP 的构建项目是由 Lambda 应用程序创建的。构建项目使用 aws/lambda/nodejs:10-1.0 有两个问题:

  • SAM CLI 版本已过时
  • 未安装 Java,因为该图像旨在用于基于 nodejs 的 Lambda 函数。需要 Java 才能构建基于 Java 的 AWS Lambda 函数

以下 buildspec.yaml 可用于修复这两个问题:

---
version: '0.2'
phases:
  install:
    commands:
    - echo Entered the install phase...
    - npm install --global lerna
    - lerna bootstrap --concurrency=1 -- --production
    - yum install -y amazon-linux-extras which
    - amazon-linux-extras install java-openjdk11
    - pip install aws-sam-cli --upgrade
  build:
    commands:
    - sam build
    - sam package --s3-bucket cf-templates-fgoi5xu7d2hs-us-east-1 --output-template-file
      template-export.yml
artifacts:
  files:
  - template-export.yml

【讨论】:

  • Hey Kaustubh,我之前尝试将sam build 添加到buildspec.yml 文件的构建阶段,首先它说Architectures 不是有效的配置值。我尝试删除它,然后它说nodejs14.x 不是有效的Runtime 配置值。我没有尝试比这更进一步。我在正确的轨道上吗?我将我的问题更新为底部的错误消息
  • 是的,这两个错误都表明 sam cli 版本过旧,因为它们都是 2021 年发布的功能。我实际上能够同时运行上述 buildspec.yaml 并将您的资源部署到我的帐户中,我所做的唯一更改是注释掉权限边界,因为它是特定于帐户的。
  • 作为参考,我使用图像aws/codebuild/standard:5.0 进行代码构建
  • 我的项目是否指向旧版本的代码构建?这个项目只有几周的历史,所以它应该已经有了一个相当新的版本。我是否需要在 buildspec.yml 构建脚本中更新 sam 的版本?
  • 您在构建项目中使用了哪个 docker 镜像? SAM 的默认版本可能取决于此。 aws/codebuild/standard:5.0 为我工作。如果没有其他方法,您可以尝试在 buildspec.yaml 中更新 SAM CLI 版本。
【解决方案2】:

有用于 Java 和 NodeJS 的 Docker 映像。我建议使用 Docker 映像作为 lambda 的基础。

对于 Java

以下示例 Dockerfile:

FROM public.ecr.aws/lambda/java:11

# Copy function code and runtime dependencies from Gradle layout
COPY build/classes/java/main ${LAMBDA_TASK_ROOT}
COPY build/dependency/* ${LAMBDA_TASK_ROOT}/lib/

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "com.example.LambdaHandler::handleRequest" ]

用于准备运行时依赖项的示例 Gradle 任务定义:

task copyRuntimeDependencies(type: Copy) {
    from configurations.runtimeClasspath
    into 'build/dependency'
}

对于 NodeJS

以下示例 Dockerfile:

FROM public.ecr.aws/lambda/nodejs:12

# Copy function code
COPY app.js ${LAMBDA_TASK_ROOT}

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "app.handler" ]

在本地测试两个图像

构建你的形象:

docker build -t <image name> .

在本地运行您的图像:

docker run -p 9000:8080 <image name>

在单独的终端中,您可以使用 cURL 在本地调用该函数:

curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'

Reference:

您也可以尝试创建多层 lambda。不确定它是否有效。

【讨论】:

  • 我的项目是基于 CloudFormation 构建的 AWS Lambda Application,但我无法为 AWS CodeBuild 自定义映像。我想要做的是自定义 AWS CodeBuild 映像,以便它安装了 NodeJS 和 Java。然后除了 Java lambda 之外,它还可以构建 NodeJS lambda。我的项目在本地工作,但由于未安装 Java,因此无法在 AWS CodeBuild 实例上构建。另一个答案是在构建机器上安装 Java,但我真正想要的是 Java 已经存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 1970-01-01
相关资源
最近更新 更多