在 Amazon Graviton2 机型上使用自定义 Runtime 开发无服务 JAVA 应用

Java
Amazon EC2
0
0
{"value":"### **介绍**\n\nAmazon Graviton 处理器是亚马逊云科技针对运行在 Amazon Elastic Compute Cloud (Amazon EC2) 实例的云上工作负载,而专门开发的具备高性价比的 ARM 架构 CPU 芯片。自从2019年问世以来,Amazon Graviton 芯片极大地提高了云用户的投资回报率(ROI)和云上资源的拥有成本(TCO)。作为目前 Amazon Graviton 芯片家族的主力,相比同配置的 X86 芯片,Amazon Graviton2 能够带来最多40%的性能提升。Amazon Serverless Application Model (简称 Amazon SAM) ,是一款由亚马逊云科技研发的,帮助开发者更快速高效地开发云上[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)应用的利器(可以查看相关的 workshop,以便快速理解 Amazon SAM)。\n\nAmazon SAM 在 X86 平台上为广大[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)应用开发者提供了便利。那么,如何将 Amazon SAM 搬到 Amazon Graviton2 上,使得开发者既能享受 Amazon Graviton2 带来的性价比,也能充分利用 Amazon SAM 强大的功能,以加速应用开发呢?\n\n同时,由于开发者各自的技术栈千差万别,而亚马逊云科技目前支持的编程语言种类和运行时环境版本均有限,对于特定的、不默认支持的运行时环境,Amazon SAM 初学者可能会感到无从下手。\n\n本篇就以 JAVA 18(亚马逊云科技默认支持 JAVA8 及 JAVA11)运行时为例,详细演示如何在 Amazon Graviton2 上,利用 Amazon SAM 来开发一个入门的 JAVA [无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)应用。\n\n与 Amazon SAM 相关的 workshop:\n[https://catalog.us-east-1.prod.workshops.aws/workshops/d21ec850-bab5-4276-af98-a91664f8b161/en-US](https://catalog.us-east-1.prod.workshops.aws/workshops/d21ec850-bab5-4276-af98-a91664f8b161/en-US)\n\n#### **整体架构**\n\n下图展示了本文所示例子的整体架构。\n\n首先,我们在 Amazon Graviton2 芯片的 EC2 实例上创建一个开发环境并安装 Amazon SAM CLI;然后,我们在实例上编写应用的代码;开发完成后,我们使用 Amazon SAM CLI 的相关命令构建,测试以及部署我们的应用;最后,我们使用 Amazon CloudFormation 将我们的应用部署在 [Amazon API Gateway](https://aws.amazon.com/cn/api-gateway/?trk=cndc-detail) 和 Amazon Lambda 上。\n\n![image.png](https://dev-media.amazoncloud.cn/1046a891f0e44e3c8221392d90e543ab_image.png)\n\n#### **搭建开发环境**\n\n在 X86 平台的很多 Amazon SAM 开发教程中,我们会用到 Amazon Cloud9 这个服务。Amazon Cloud9 可以使我们方便快捷地搭建起一个运行在云端的 IDE。很遗憾,目前用户还不能创建基于 Amazon Graviton2 实例的 Amazon Cloud9 环境。因此,在本文示例中,我们将在一个 Amazon Gravation2 实例上从头搭建一个 Amazon SAM 开发环境。具体步骤如下:\n\n1. 在亚马逊云科技控制台启动一个 Amazon Graviton2 实例,例如 medium。这个演示中我们使用 Amazon Linux 2 操作系统,可以阅读相关文章查看如何启动一个 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例的详细步骤。\n\n2. 在 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例上安装 Amazon SAM CLI 。可以阅读相关文章查看安装的详细步骤。请注意安装详细步骤中的第三步“Install Docker”,虽然文档中标注为 Optional,但是本例中我们需要安装,不要跳过,因为我们会使用 Docker 来构建我们的自定义 JAVA 运行时。在写这篇文章的时候,安装详细步骤里面的第四步“Install the Amazon SAM CLI”,需要针对 Amazon Graviton2 实例做出一些调整才可以顺利进行。文档中在 ARM 平台上的安装命令是“pip install aws-sam-cli”,需要被替换如下:\n\n- sudo yum –y update\n- sudo yum -y install gcc\n- sudo yum install python3-devel\n- pip3 install aws-sam-cli\n\n启动 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例的相关文章:\n[https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/EC2_GetStarted.html#ec2-launch-instance](https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/EC2_GetStarted.html#ec2-launch-instance)\n\n安装 Amazon SAM CLI 相关文章:\n[https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html](https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html)\n\n#### **开发代码**\n\n执行完上述步骤,我们就搭建了开发本文例子的开发环境。由于我们会开发[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)应用,后续的代码逻辑会放置在 Amazon Lambda Function 中运行,因此开发环境中无需安装 JDK。我们会使用 Amazon SAM CLI 来协助我们编写代码,因为 Amazon SAM 提供了很多项目模板,所以我们不必从头开始编写我们的代码。\n\n##### **初始化项目**\n\n阅读文章查看使用 Amazon SAM CLI 初始化一个 hello-world 应用的详细步骤。由于我们还要基于自动生成的代码模板做进一步修改,因此详细步骤中的内容,我们仅需要执行第二步 “Build your application” 之前的内容(不包括第二步)。稍后,完成代码编写后,我们会构建和部署我们的应用。\n\n关于使用 Amazon SAM CLI 初始化一个 hello-world 应用的详细步骤文章:\n[https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html)\n\n在执行 “sam init” 命令之后,SAM CLI 会收集一系列问题的答案,以便创建符合我们要求的项目代码模板。以下是我们针对本文示例的问题回答:\n1. Which template source would you like to use? 1 – [Amazon Q](https://aws.amazon.com/cn/q/?trk=cndc-detail)uick Start Templates\n2. Choose an [Amazon Q](https://aws.amazon.com/cn/q/?trk=cndc-detail)uick Start application template? 1 – Hello World Example\n3. Use the most popular runtime and package type? (Python and zip) [y/N]: N\n4. Which runtime would you like to use? 5 – java11\n5. What package type would you like to use? 1 – Zip\n6. Which dependency manager would you like to use? 2 – maven\n7. Would you like to enable X-Ray tracing on the function(s) in your application? N\n\n对于问题4,由于 Amazon SAM 当前默认只支持 JAVA8 和11(这也是本文写作的目的之一——使用任意 JAVA 版本运行时),我们选择 JAVA11 版本。我们当前只是想要利用 Amazon SAM CLI 自动生成的代码框架,因此 JAVA 版本的选择在目前无关紧要。\n\n从 Amazon SAM CLI 自动生成的 JAVA 代码中可以看到,代码所完成的逻辑非常简单,在生成的 Lambda 函数的实现中,我们只是以 JSON 格式返回一个“hello world”字符串以及调用者的 IP 地址。\n\n![image.png](https://dev-media.amazoncloud.cn/df7eb38c9fee4642bedb8f6fe717cadc_image.png)\n\n##### **构建自定义运行时**\n\n由于 JAVA 18 不是一个 Amazon SAM 默认支持的 JAVA 运行时版本,所以我们必须自己构建运行时。这篇文章详细讲述了如何为 Lambda 函数构建一个任意版本的 JAVA 运行时。其中,modular runtime image, class data sharing 以及 tiered compilation 等技术被用来缩小运行时体积以及提升 Lambda 函数的性能。在我们的文章中,我们也会借鉴这些技术来优化 Lambda 函数的冷启动问题。在本文的例子中,我们使用 Docker container 来构建我们的运行时。由于我们的代码最终会运行在 ARM 平台上,所以镜像需要在 arm64 版本的 Linux 镜像上来构建。这也是下面 Dockerfile 截图中使用 “–platform=linux/arm64/v8” 参数的原因。\n\n关于如何为 Lambda 函数构建一个任意版本的 JAVA 运行时文章:\n[https://aws.amazon.com/cn/blogs/compute/build-a-custom-java-runtime-for-aws-lambda/](https://aws.amazon.com/cn/blogs/compute/build-a-custom-java-runtime-for-aws-lambda/)\n\nDockerfile 的其他部分与 x86 平台上的内容一致。Dockerfile 中的内容被分成了几个部分,通过相关的注释不难理解各部分的作用。完整的文件内容如下:\n\n![image.png](https://dev-media.amazoncloud.cn/c13780b06d8440ba86e6dc2945f031df_image.png)\n\n需要注意的是 Dockerfile 的最后一段,runtime.tar 的内部结构是固定的,这是 Lambda 函数自定义运行时所要求的。如果读者对于相关打包要求不熟悉,可参考此**文档**:[https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html)。\n\n##### **在 Amazon SAM Template 中指定自定义运行时**\n\n在 Amazon SAM 应用开发中,一个很关键的部分就是 template.yaml 文件的编写。自定义运行时的指定也需要在这个文件中进行。以下是本例中 template.yaml 文件需要修改的关键部分:\n\n![image.png](https://dev-media.amazoncloud.cn/0871c4687573416b98951c80ab392ce5_image.png)\n\n可以参考此**文档**:[https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/building-custom-runtimes.html](https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/building-custom-runtimes.html)查看在 Amazon SAM 中构建自定义运行时的详细步骤。注意这里所指的“构建运行时”与文章前面“构建自定义运行时”部分的“运行时”是同一个,我们前面编写的 Dockerfile 需要在此处被调用。template.yaml 文件针对于本文示例的修改涉及三处(上图红框部分),分别解释如下:\n\n- HelloWorldFunction.Properties.Runtime 需要设置为“provided.al2”,而不是通常的“provided”(x86架构)。该值表明 Lambda 函数会运行于自定义运行时,“provided.al2”表示未来的运行时是 arm 架构的。\n- HelloWorldFunction.Properties.Architectures 需要设置为“arm64”。\n- HelloWorldFunction.Metadata.BuildMethod 需要设置为“makefile”。\n\n依照 Amazon SAM 构建自定义运行时的要求,在 Resources.HelloWorldFunction.Metadata.BuildMethod 设置为 “makefile”以后,我们需要在一个名为“makefile”的文件中编写真正的构建命令脚本,并且 makefile 应该位于Resources.HelloWorldFunction.Properties.CodeUri 所指定的目录之下。\n\n本例中的 makefile 的完整内容如下:\n\n![image.png](https://dev-media.amazoncloud.cn/d6095db84e4e4e309b3c51b28da0657a_image.png)\n\n首先,我们使用 Docker 命令来构建 JAVA 18 的运行时;然后,我们使用生成的镜像来启动一个容器,并将镜像内的运行时文件包抽取出来。最后一步稍显复杂,其目的如下:SAM CLI 进行构建时,会将所生成的中间 artifacts 存放于特定隐藏目录,然后将该目录内文件统一打包。此处如果我们不对 runtime.tar 进行解包,就会造成 Amazon SAM CLI 打包生成的文件包内多一层目录,后续 Lambda 函数调用时,会遇到无法找到 bootstrap 文件的错误。\n\n#### **使用 Amazon SAM 构建和部署应用**\n\n做完上述准备后,我们就可以使用 Amazon SAM CLI 来构建和部署我们的应用了。进入应用的根目录,运行“sam build”命令,就会启动构建过程。我们的应用中创建了一个 Lambda 函数和一个 API Gateway。如果需要在本机进行测试,我们可以在构建完成后,在命令行运行“sam local start-api”来启动一个本地的 API Gateway 环境来进行测试。以下是一个示例:\n\n![image.png](https://dev-media.amazoncloud.cn/7d234e393d6e4aa688001f44b326e165_image.png)\n\n如上图所示,运行完后,会生成一个本地 API Gateway 的 URL。由于我们在应用的 template.yaml 文件中定义的 API Gateway 方法的 Path 为“/hello”,所以要测试本例中的方法,需要使用如下地址测试:[http://127.0.0.1:3000/hello](http://127.0.0.1:3000/hello)。在命令行中输入“curl [http://127.0.0.1:3000/hello](http://127.0.0.1:3000/hello)”之后,会得到如下结果:\n\n```\\n{ \\"message\\": \\"hello world\\", \\"location\\": \\"44.192.90.179\\" }\\n```\n确认我们的代码功能正常之后,我们可以继续将我们的应用部署到云端。执行如下命令:\n\n```\\nsam deploy –guided\\n```\n像之前创建 Amazon SAM 应用一样,我们也需要回答一系列问题来完成交互式部署,对于本文中的例子,所有问题均可直接回车,选择默认值,除了以下这个问题:\n\n```\\nHelloWorldFunction may not have authorization defined, Is this okay? [y/N].\\n```\n此处选择“y”。此问题是提示我们,应用中定义的 Lambda 函数配置了 API Gateway,但是并没有为其关联 Authorization 机制,会导致部署之后生成的 URL 对整个互联网开放,具有安全隐患。为了保持简洁,我们示例中选择忽略这个提醒,但是在生产环境中,不建议如此设置。命令执行完成后,会输出如下信息:\n\n![image.png](https://dev-media.amazoncloud.cn/0788d35b17ed49298de71d79eeafb845_image.png)\n\n基于我们应用 template.yaml 中的定义,命令行中最后会输出可以调用的 API Gateway 方法的 URL(上图红框所示)。\n\n我们可以在浏览器或命令行中访问这个 URL,看到和本地测试时类似的结果。至此,我们完整的演示了整个应用的开发流程,查看相关文章:[https://github.com/szipan/lambda-on-graviton2](https://github.com/szipan/lambda-on-graviton2)可以获得完整的示例代码。\n\n### **结论**\n\nAmazon Graviton2 给了亚马逊云科技用户一个非常具有竞争力、高性价比的计算平台新选择。因此,开发者们会希望尝试将他们运行在传统 x86 架构上的工作和负载迁移到 Amazon Graviton2 架构上。对于云上[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)应用的开发,SAM 是一个强有力的工具,其提供了单部署配置、本地调试测试功能;内置了相关的最佳实践,可以加速开发工作;并且其基于 Amazon CloudFormation,可以使用 CDK 进行部署,平滑了开发者的学习曲线。考虑到目前 JAVA 仍是最流行的开发语言之一,我们撰写了这篇文章,以期对想要在 Amazon Graviton2 上进行[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)应用开发的开发者们,尤其是[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)应用的初学者们,提供相关的帮助。\n\n相信读者使用了上述服务后,可以感受到相关服务为开发工作带来的好处,以上服务仍在不断演进中,感兴趣的读者可以保持关注。\n\n##### **本篇作者**\n**宋孜攀**\n西云数据解决方案架构师\n\n[阅读原文](https://aws.amazon.com/cn/blogs/china/developing-non-service-java-applications-using-custom-runtime-on-amazon-graviton2-models/?sc_channel=sm&sc_campaign=blog&sc_publisher=wechatdev&sc_detail=)\n","render":"<h3><a id=\\"_0\\"></a><strong>介绍</strong></h3>\\n<p>Amazon Graviton 处理器是亚马逊云科技针对运行在 Amazon Elastic Compute Cloud (Amazon EC2) 实例的云上工作负载,而专门开发的具备高性价比的 ARM 架构 CPU 芯片。自从2019年问世以来,Amazon Graviton 芯片极大地提高了云用户的投资回报率(ROI)和云上资源的拥有成本(TCO)。作为目前 Amazon Graviton 芯片家族的主力,相比同配置的 X86 芯片,Amazon Graviton2 能够带来最多40%的性能提升。Amazon Serverless Application Model (简称 Amazon SAM) ,是一款由亚马逊云科技研发的,帮助开发者更快速高效地开发云上无服务器应用的利器(可以查看相关的 workshop,以便快速理解 Amazon SAM)。</p>\n<p>Amazon SAM 在 X86 平台上为广大无服务器应用开发者提供了便利。那么,如何将 Amazon SAM 搬到 Amazon Graviton2 上,使得开发者既能享受 Amazon Graviton2 带来的性价比,也能充分利用 Amazon SAM 强大的功能,以加速应用开发呢?</p>\n<p>同时,由于开发者各自的技术栈千差万别,而亚马逊云科技目前支持的编程语言种类和运行时环境版本均有限,对于特定的、不默认支持的运行时环境,Amazon SAM 初学者可能会感到无从下手。</p>\n<p>本篇就以 JAVA 18(亚马逊云科技默认支持 JAVA8 及 JAVA11)运行时为例,详细演示如何在 Amazon Graviton2 上,利用 Amazon SAM 来开发一个入门的 JAVA 无服务器应用。</p>\n<p>与 Amazon SAM 相关的 workshop:<br />\\n<a href=\\"https://catalog.us-east-1.prod.workshops.aws/workshops/d21ec850-bab5-4276-af98-a91664f8b161/en-US\\" target=\\"_blank\\">https://catalog.us-east-1.prod.workshops.aws/workshops/d21ec850-bab5-4276-af98-a91664f8b161/en-US</a></p>\\n<h4><a id=\\"_13\\"></a><strong>整体架构</strong></h4>\\n<p>下图展示了本文所示例子的整体架构。</p>\n<p>首先,我们在 Amazon Graviton2 芯片的 EC2 实例上创建一个开发环境并安装 Amazon SAM CLI;然后,我们在实例上编写应用的代码;开发完成后,我们使用 Amazon SAM CLI 的相关命令构建,测试以及部署我们的应用;最后,我们使用 Amazon CloudFormation 将我们的应用部署在 Amazon API Gateway 和 Amazon Lambda 上。</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/1046a891f0e44e3c8221392d90e543ab_image.png\\" alt=\\"image.png\\" /></p>\n<h4><a id=\\"_21\\"></a><strong>搭建开发环境</strong></h4>\\n<p>在 X86 平台的很多 Amazon SAM 开发教程中,我们会用到 Amazon Cloud9 这个服务。Amazon Cloud9 可以使我们方便快捷地搭建起一个运行在云端的 IDE。很遗憾,目前用户还不能创建基于 Amazon Graviton2 实例的 Amazon Cloud9 环境。因此,在本文示例中,我们将在一个 Amazon Gravation2 实例上从头搭建一个 Amazon SAM 开发环境。具体步骤如下:</p>\n<ol>\\n<li>\\n<p>在亚马逊云科技控制台启动一个 Amazon Graviton2 实例,例如 medium。这个演示中我们使用 Amazon Linux 2 操作系统,可以阅读相关文章查看如何启动一个 Amazon EC2 实例的详细步骤。</p>\n</li>\\n<li>\\n<p>在 Amazon EC2 实例上安装 Amazon SAM CLI 。可以阅读相关文章查看安装的详细步骤。请注意安装详细步骤中的第三步“Install Docker”,虽然文档中标注为 Optional,但是本例中我们需要安装,不要跳过,因为我们会使用 Docker 来构建我们的自定义 JAVA 运行时。在写这篇文章的时候,安装详细步骤里面的第四步“Install the Amazon SAM CLI”,需要针对 Amazon Graviton2 实例做出一些调整才可以顺利进行。文档中在 ARM 平台上的安装命令是“pip install aws-sam-cli”,需要被替换如下:</p>\n</li>\\n</ol>\n<ul>\\n<li>sudo yum –y update</li>\n<li>sudo yum -y install gcc</li>\n<li>sudo yum install python3-devel</li>\n<li>pip3 install aws-sam-cli</li>\n</ul>\\n<p>启动 Amazon EC2 实例的相关文章:<br />\\n<a href=\\"https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/EC2_GetStarted.html#ec2-launch-instance\\" target=\\"_blank\\">https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/EC2_GetStarted.html#ec2-launch-instance</a></p>\\n<p>安装 Amazon SAM CLI 相关文章:<br />\\n<a href=\\"https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html\\" target=\\"_blank\\">https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html</a></p>\\n<h4><a id=\\"_40\\"></a><strong>开发代码</strong></h4>\\n<p>执行完上述步骤,我们就搭建了开发本文例子的开发环境。由于我们会开发无服务器应用,后续的代码逻辑会放置在 Amazon Lambda Function 中运行,因此开发环境中无需安装 JDK。我们会使用 Amazon SAM CLI 来协助我们编写代码,因为 Amazon SAM 提供了很多项目模板,所以我们不必从头开始编写我们的代码。</p>\n<h5><a id=\\"_44\\"></a><strong>初始化项目</strong></h5>\\n<p>阅读文章查看使用 Amazon SAM CLI 初始化一个 hello-world 应用的详细步骤。由于我们还要基于自动生成的代码模板做进一步修改,因此详细步骤中的内容,我们仅需要执行第二步 “Build your application” 之前的内容(不包括第二步)。稍后,完成代码编写后,我们会构建和部署我们的应用。</p>\n<p>关于使用 Amazon SAM CLI 初始化一个 hello-world 应用的详细步骤文章:<br />\\n<a href=\\"https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html\\" target=\\"_blank\\">https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html</a></p>\\n<p>在执行 “sam init” 命令之后,SAM CLI 会收集一系列问题的答案,以便创建符合我们要求的项目代码模板。以下是我们针对本文示例的问题回答:</p>\n<ol>\\n<li>Which template source would you like to use? 1 – Amazon Quick Start Templates</li>\n<li>Choose an Amazon Quick Start application template? 1 – Hello World Example</li>\n<li>Use the most popular runtime and package type? (Python and zip) [y/N]: N</li>\n<li>Which runtime would you like to use? 5 – java11</li>\n<li>What package type would you like to use? 1 – Zip</li>\n<li>Which dependency manager would you like to use? 2 – maven</li>\n<li>Would you like to enable X-Ray tracing on the function(s) in your application? N</li>\n</ol>\\n<p>对于问题4,由于 Amazon SAM 当前默认只支持 JAVA8 和11(这也是本文写作的目的之一——使用任意 JAVA 版本运行时),我们选择 JAVA11 版本。我们当前只是想要利用 Amazon SAM CLI 自动生成的代码框架,因此 JAVA 版本的选择在目前无关紧要。</p>\n<p>从 Amazon SAM CLI 自动生成的 JAVA 代码中可以看到,代码所完成的逻辑非常简单,在生成的 Lambda 函数的实现中,我们只是以 JSON 格式返回一个“hello world”字符串以及调用者的 IP 地址。</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/df7eb38c9fee4642bedb8f6fe717cadc_image.png\\" alt=\\"image.png\\" /></p>\n<h5><a id=\\"_66\\"></a><strong>构建自定义运行时</strong></h5>\\n<p>由于 JAVA 18 不是一个 Amazon SAM 默认支持的 JAVA 运行时版本,所以我们必须自己构建运行时。这篇文章详细讲述了如何为 Lambda 函数构建一个任意版本的 JAVA 运行时。其中,modular runtime image, class data sharing 以及 tiered compilation 等技术被用来缩小运行时体积以及提升 Lambda 函数的性能。在我们的文章中,我们也会借鉴这些技术来优化 Lambda 函数的冷启动问题。在本文的例子中,我们使用 Docker container 来构建我们的运行时。由于我们的代码最终会运行在 ARM 平台上,所以镜像需要在 arm64 版本的 Linux 镜像上来构建。这也是下面 Dockerfile 截图中使用 “–platform=linux/arm64/v8” 参数的原因。</p>\n<p>关于如何为 Lambda 函数构建一个任意版本的 JAVA 运行时文章:<br />\\n<a href=\\"https://aws.amazon.com/cn/blogs/compute/build-a-custom-java-runtime-for-aws-lambda/\\" target=\\"_blank\\">https://aws.amazon.com/cn/blogs/compute/build-a-custom-java-runtime-for-aws-lambda/</a></p>\\n<p>Dockerfile 的其他部分与 x86 平台上的内容一致。Dockerfile 中的内容被分成了几个部分,通过相关的注释不难理解各部分的作用。完整的文件内容如下:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/c13780b06d8440ba86e6dc2945f031df_image.png\\" alt=\\"image.png\\" /></p>\n<p>需要注意的是 Dockerfile 的最后一段,runtime.tar 的内部结构是固定的,这是 Lambda 函数自定义运行时所要求的。如果读者对于相关打包要求不熟悉,可参考此<strong>文档</strong>:<a href=\\"https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html\\" target=\\"_blank\\">https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html</a>。</p>\\n<h5><a id=\\"_Amazon_SAM_Template__79\\"></a><strong>在 Amazon SAM Template 中指定自定义运行时</strong></h5>\\n<p>在 Amazon SAM 应用开发中,一个很关键的部分就是 template.yaml 文件的编写。自定义运行时的指定也需要在这个文件中进行。以下是本例中 template.yaml 文件需要修改的关键部分:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/0871c4687573416b98951c80ab392ce5_image.png\\" alt=\\"image.png\\" /></p>\n<p>可以参考此<strong>文档</strong>:<a href=\\"https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/building-custom-runtimes.html\\" target=\\"_blank\\">https://docs.aws.amazon.com/zh_cn/serverless-application-model/latest/developerguide/building-custom-runtimes.html</a>查看在 Amazon SAM 中构建自定义运行时的详细步骤。注意这里所指的“构建运行时”与文章前面“构建自定义运行时”部分的“运行时”是同一个,我们前面编写的 Dockerfile 需要在此处被调用。template.yaml 文件针对于本文示例的修改涉及三处(上图红框部分),分别解释如下:</p>\\n<ul>\\n<li>HelloWorldFunction.Properties.Runtime 需要设置为“provided.al2”,而不是通常的“provided”(x86架构)。该值表明 Lambda 函数会运行于自定义运行时,“provided.al2”表示未来的运行时是 arm 架构的。</li>\n<li>HelloWorldFunction.Properties.Architectures 需要设置为“arm64”。</li>\n<li>HelloWorldFunction.Metadata.BuildMethod 需要设置为“makefile”。</li>\n</ul>\\n<p>依照 Amazon SAM 构建自定义运行时的要求,在 Resources.HelloWorldFunction.Metadata.BuildMethod 设置为 “makefile”以后,我们需要在一个名为“makefile”的文件中编写真正的构建命令脚本,并且 makefile 应该位于Resources.HelloWorldFunction.Properties.CodeUri 所指定的目录之下。</p>\n<p>本例中的 makefile 的完整内容如下:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/d6095db84e4e4e309b3c51b28da0657a_image.png\\" alt=\\"image.png\\" /></p>\n<p>首先,我们使用 Docker 命令来构建 JAVA 18 的运行时;然后,我们使用生成的镜像来启动一个容器,并将镜像内的运行时文件包抽取出来。最后一步稍显复杂,其目的如下:SAM CLI 进行构建时,会将所生成的中间 artifacts 存放于特定隐藏目录,然后将该目录内文件统一打包。此处如果我们不对 runtime.tar 进行解包,就会造成 Amazon SAM CLI 打包生成的文件包内多一层目录,后续 Lambda 函数调用时,会遇到无法找到 bootstrap 文件的错误。</p>\n<h4><a id=\\"_Amazon_SAM__99\\"></a><strong>使用 Amazon SAM 构建和部署应用</strong></h4>\\n<p>做完上述准备后,我们就可以使用 Amazon SAM CLI 来构建和部署我们的应用了。进入应用的根目录,运行“sam build”命令,就会启动构建过程。我们的应用中创建了一个 Lambda 函数和一个 API Gateway。如果需要在本机进行测试,我们可以在构建完成后,在命令行运行“sam local start-api”来启动一个本地的 API Gateway 环境来进行测试。以下是一个示例:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/7d234e393d6e4aa688001f44b326e165_image.png\\" alt=\\"image.png\\" /></p>\n<p>如上图所示,运行完后,会生成一个本地 API Gateway 的 URL。由于我们在应用的 template.yaml 文件中定义的 API Gateway 方法的 Path 为“/hello”,所以要测试本例中的方法,需要使用如下地址测试:<a href=\\"http://127.0.0.1:3000/hello\\" target=\\"_blank\\">http://127.0.0.1:3000/hello</a>。在命令行中输入“curl <a href=\\"http://127.0.0.1:3000/hello\\" target=\\"_blank\\">http://127.0.0.1:3000/hello</a>”之后,会得到如下结果:</p>\\n<pre><code class=\\"lang-\\">{ &quot;message&quot;: &quot;hello world&quot;, &quot;location&quot;: &quot;44.192.90.179&quot; }\\n</code></pre>\\n<p>确认我们的代码功能正常之后,我们可以继续将我们的应用部署到云端。执行如下命令:</p>\n<pre><code class=\\"lang-\\">sam deploy –guided\\n</code></pre>\\n<p>像之前创建 Amazon SAM 应用一样,我们也需要回答一系列问题来完成交互式部署,对于本文中的例子,所有问题均可直接回车,选择默认值,除了以下这个问题:</p>\n<pre><code class=\\"lang-\\">HelloWorldFunction may not have authorization defined, Is this okay? [y/N].\\n</code></pre>\\n<p>此处选择“y”。此问题是提示我们,应用中定义的 Lambda 函数配置了 API Gateway,但是并没有为其关联 Authorization 机制,会导致部署之后生成的 URL 对整个互联网开放,具有安全隐患。为了保持简洁,我们示例中选择忽略这个提醒,但是在生产环境中,不建议如此设置。命令执行完成后,会输出如下信息:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/0788d35b17ed49298de71d79eeafb845_image.png\\" alt=\\"image.png\\" /></p>\n<p>基于我们应用 template.yaml 中的定义,命令行中最后会输出可以调用的 API Gateway 方法的 URL(上图红框所示)。</p>\n<p>我们可以在浏览器或命令行中访问这个 URL,看到和本地测试时类似的结果。至此,我们完整的演示了整个应用的开发流程,查看相关文章:<a href=\\"https://github.com/szipan/lambda-on-graviton2\\" target=\\"_blank\\">https://github.com/szipan/lambda-on-graviton2</a>可以获得完整的示例代码。</p>\\n<h3><a id=\\"_128\\"></a><strong>结论</strong></h3>\\n<p>Amazon Graviton2 给了亚马逊云科技用户一个非常具有竞争力、高性价比的计算平台新选择。因此,开发者们会希望尝试将他们运行在传统 x86 架构上的工作和负载迁移到 Amazon Graviton2 架构上。对于云上无服务器应用的开发,SAM 是一个强有力的工具,其提供了单部署配置、本地调试测试功能;内置了相关的最佳实践,可以加速开发工作;并且其基于 Amazon CloudFormation,可以使用 CDK 进行部署,平滑了开发者的学习曲线。考虑到目前 JAVA 仍是最流行的开发语言之一,我们撰写了这篇文章,以期对想要在 Amazon Graviton2 上进行无服务器应用开发的开发者们,尤其是无服务器应用的初学者们,提供相关的帮助。</p>\n<p>相信读者使用了上述服务后,可以感受到相关服务为开发工作带来的好处,以上服务仍在不断演进中,感兴趣的读者可以保持关注。</p>\n<h5><a id=\\"_134\\"></a><strong>本篇作者</strong></h5>\\n<p><strong>宋孜攀</strong><br />\\n西云数据解决方案架构师</p>\n<p><a href=\\"https://aws.amazon.com/cn/blogs/china/developing-non-service-java-applications-using-custom-runtime-on-amazon-graviton2-models/?sc_channel=sm&amp;sc_campaign=blog&amp;sc_publisher=wechatdev&amp;sc_detail=\\" target=\\"_blank\\">阅读原文</a></p>\n"}
0
目录
关闭