无服务器架构在由第 3 方完全管理的临时容器中运行自定义代码。自定义代码通常是完整应用程序的一小部分。它也被称为函数。这为无服务器架构提供了另一个名称,即功能即服务 (FaaS)。容器是短暂的,因为它可能只持续一次调用。容器可以重复使用,但这不是您可以依赖的东西。作为开发人员,您将代码上传到 FaaS 平台,然后该服务会处理基础架构的所有容量、扩展、修补和管理,以运行您的代码。
使用无服务器架构构建的应用程序遵循事件驱动的方法。例如,应用程序中发生了一个活动,例如单击。
这与经典架构非常不同,在经典架构中,应用程序代码通常部署在 Tomcat 或 WildFly 等应用程序服务器中。扩展您的应用程序意味着启动应用程序服务器的额外实例或使用打包的应用程序服务器启动额外的容器。负载平衡器需要使用新的 IP 地址进行更新。操作系统需要打补丁、升级和维护。
Serverless Architectures 解释了经典编程模型和这种新的无服务器架构之间的区别。
FaaS 平台将您的应用程序划分为多个功能。每个功能都部署在 FaaS 中。该服务启动额外的计算实例以满足您的应用程序的可扩展性需求。 FaaS 平台提供执行环境并负责启动和拆除容器以运行您的功能。
阅读 Serverless Architectures 了解有关这些图像的更多详细信息。
FaaS 的一大优势是您只需为计算时间付费,即您的代码运行的时间。当您的代码未运行时,不收取任何费用。
查看 Functions 与 VM 和 Container 的不同之处的另一种方法:
请注意,Linux 容器而不是 Docker 容器被用作 AWS Lambda 的实现。
正如在 Serverless Architectures 中引用的那样,以下推文提供了一个快速答案:
如果您的 PaaS 可以在 20 毫秒内有效地启动运行半秒的实例,那么就称它为无服务器。 https://t.co/S3YzvqFYLR
— adrian cockcroft (@adrianco) 2016 年 5 月 28 日
换句话说,大多数 PaaS 应用程序并不适合针对每个请求启动和关闭整个应用程序,而 FaaS 平台正是这样做的。
使用 FaaS 抽象后端解释不同 *aaS 产品的区别。博客中的图片如下:
Serverless Architectures 还详细介绍了 FaaS 是什么和不是什么。
AWS Lambda、Google Cloud Functions 和 Azure Functions 是运行无服务器应用程序的一些选项。
此博客将展示如何编写您的第一个 AWS Lambda 函数。
AWS Lambda 是 Amazon Web Services 的 FaaS 服务。它在高可用性计算基础架构上运行您的代码,并执行计算资源的所有管理,包括服务器和操作系统维护、容量配置和自动扩展、代码监控和日志记录。
AWS Lambda 在您的代码运行期间以 100 毫秒为增量向您收费。在 AWS 中存储 Lambda 函数没有任何相关费用。每月前 100 万个请求是免费的,之后的价格是象征性的。阅读有关 Lambda 定价 的更多详细信息。它还通过向 AWS CloudWatch 提供实时指标和日志来提供性能可见性。您需要做的就是编写代码!
这是一个快速介绍:
另请查看 AWS ReInvent 2016 中 AWS Lambda 的新增功能:
另请查看 AWS ReInvent 2016 中的无服务器架构模式和最佳实践:
您在 AWS Lambda 上运行的代码称为 Lambda 函数。您可以将代码作为 zip 文件上传或使用 AWS Lambda 管理控制台 进行设计。内置了对 AWS SDK 的支持,这简化了调用其他 AWS 服务的能力。
简而言之,Lambda 是可扩展的、无服务器的、在云中计算的。
AWS Lambda 提供了几种执行环境:
本博客将展示:
此博客中的完整代码可在 github.com/arun-gupta/serverless/tree/master/aws/hellocouchbase 获得。
首先,让我们看一下将用于此 Lambda 函数的 Java 应用程序。 Java 中 Lambda 函数的编程模型提供了有关如何使用 Java 编写 Lambda 函数代码的更多详细信息。
我们的 Lambda 函数将实现预定义接口 com.amazonaws.services.lambda.runtime.RequestHandler
。代码如下:
public class HelloCouchbase implements RequestHandler<Request, String> { CouchbaseCluster cluster; Bucket bucket; LambdaLogger logger; @Override public String handleRequest(Request request, Context context) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); String timestamp = dateFormat.format(Calendar.getInstance().getTime()); logger = context.getLogger(); logger.log("Request received: %s" + timestamp); ButtonDocument buttonDocument = new ButtonDocument(); buttonDocument.setId(context.getAwsRequestId()); buttonDocument.setRequestId(context.getAwsRequestId()); buttonDocument.setTimestamp(String.valueOf(timestamp)); getBucket().upsert(buttonDocument.toJson()); return buttonDocument.toString(); }
handleRequest
方法是实现功能代码的地方。 Context
提供有关 Lambda 执行环境的有用信息。来自上下文的一些信息存储在一个 JSON 文档中。最后,Couchbase Java SDK API upsert
用于将 JSON 文档写入已识别的 Couchbase 实例。 Amazon EC2 上的 Couchbase 提供了在 AWS EC2 上安装 Couchbase 的完整说明。
Couchbase 服务器的信息获取方式如下:
public CouchbaseCluster getCluster() { if (null == cluster) { logger.log("env: " + System.getenv("COUCHBASE_HOST")); cluster = CouchbaseCluster.create(System.getenv("COUCHBASE_HOST")); } return cluster; }
这再次使用 Couchbase Java API CouchbaseCluster 作为 Couchbase 集群的主要入口点。 COUCHBASE_HOST
环境变量在创建 Lambda 函数时传递。在我们的例子中,这将指向在 AWS EC2 上运行的单节点 Couchbase 集群。 最近在 AWS Lambda 中引入了环境变量。
最后,您需要访问服务器中的存储桶:
public Bucket getBucket() { while (null == bucket) { logger.log("Trying to connect to the database"); bucket = getCluster().openBucket("serverless", 2L, TimeUnit.MINUTES); try { Thread.sleep(3000); } catch (Exception e) { logger.log("Thread sleep Exception: " + e.toString()); throw new RuntimeException(e); } } return bucket; }
存储桶名称为 serverless
,所有 JSON 文档都存储在其中。
一个简单的Hello World 应用程序 也可用于创建此功能。
AWS Lambda 函数需要一个部署包。此包是一个 .zip
或 .jar
文件,其中包含该函数的所有依赖项。我们的应用程序是使用 Maven 打包的,因此我们将使用 Maven 插件来创建部署包。
该应用程序包含带有以下插件片段的 pom.xml
:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.3</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin>
有关 Maven 配置的更多详细信息,请参阅在没有任何 IDE 的情况下使用 Maven 创建 .jar 部署包。 maven-shade-plugin 允许创建一个包含所有依赖项的 uber-jar。 shade
目标与 package
阶段相关联。所以 mvn package
命令将生成一个部署 jar。
使用 mvn package
命令打包应用程序。这将显示输出:
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hellocouchbase --- [INFO] Building jar: /Users/arungupta/workspaces/serverless/aws/hellocouchbase/hellocouchbase/target/hellocouchbase-1.0-SNAPSHOT.jar [INFO] [INFO] --- maven-shade-plugin:2.3:shade (default) @ hellocouchbase --- [INFO] Including com.amazonaws:aws-lambda-java-core:jar:1.1.0 in the shaded jar. [INFO] Including com.couchbase.client:java-client:jar:2.3.6 in the shaded jar. [INFO] Including com.couchbase.client:core-io:jar:1.3.6 in the shaded jar. [INFO] Including io.reactivex:rxjava:jar:1.1.8 in the shaded jar. [INFO] Replacing original artifact with shaded artifact. [INFO] Replacing /Users/arungupta/workspaces/serverless/aws/hellocouchbase/hellocouchbase/target/hellocouchbase-1.0-SNAPSHOT.jar with /Users/arungupta/workspaces/serverless/aws/hellocouchbase/hellocouchbase/target/hellocouchbase-1.0-SNAPSHOT-shaded.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
target/hello-couchbase-1.0-SNAPSHOT.jar
是将部署到 AWS Lambda 的阴影 jar。
有关创建部署包的更多详细信息,请参阅创建部署包。
使用 AWS CLI 创建 AWS Lambda 函数。这种情况下的 CLI 命令如下所示:
aws lambda create-function \ --function-name HelloWorld \ --role arn:aws:iam::<account-id>:role/service-role/myLambdaRole \ --zip-file fileb:///Users/arungupta/workspaces/serverless/aws/hellocouchbase/hellocouchbase/target/hellocouchbase-1.0-SNAPSHOT.jar \ --handler org.sample.serverless.aws.couchbase.HelloCouchbaseLambda \ --description "Hello Couchbase Lambda" \ --runtime java8 \ --region us-west-2 \ --timeout 30 \ --memory-size 1024 \ --publish
在此 CLI 中:
create-function
创建一个 Lambda 函数--function-name
提供函数名称。函数名称区分大小写。--role
指定 Lambda 在执行您的函数以访问任何其他 AWS 资源时承担的 IAM 角色 的 Amazon 资源名称 (ARN)。如果您使用 AWS 控制台执行了 Lambda 函数,则会为您创建此角色。--zip-file
指向在上一步中创建的部署包。 fileb
是 AWS CLI 特定的协议,用于指示上传的内容是二进制的。--handler
是被调用以开始执行函数的 Java 类--publish
请求 AWS Lambda 创建 Lambda 函数并将版本发布为原子操作。否则可能会创建多个版本并可能在稍后发布。Lambda 控制台显示:
使用 AWS CLI 测试 AWS Lambda 函数。
aws lambda invoke \ --function-name HelloCouchbaseLambda \ --region us-west-2 \ --payload '' \ hellocouchbase.out
它将输出显示为:
{ "StatusCode": 200 }
命令的输出存储在 hellocouchbase.out
中,如下所示:
"{\"id\":\"e6bbe71a-ca4f-11e6-95a7-95f2ed410493\",\"installationId\":null,\"requestId\":\"e6bbe71a-ca4f-11e6-95a7-95f2ed410493\",\"identityId\":null,\"timestamp\":\"2016-12-25 03:12:01.157\"}"
调用此函数会在 Couchbase 中存储一个 JSON 文档。可以使用 Couchbase Web Console 查看存储在 Couchbase 中的文档。密码是 Administrator
,密码是 EC2 实例 ID。
此 Couchbase 实例中的所有数据桶如下所示:
请注意,serverless
存储桶是手动创建的。
单击 Documents 显示存储在存储桶中的不同文档的详细信息:
单击每个文档会显示有关 JSON 文档的更多详细信息:
Lambda 函数也可以使用控制台进行测试:
如果应用程序逻辑发生变化,则需要为 Lambda 函数上传新的部署包。在这种情况下,mvn package
将创建一个部署包,aws lambda
CLI 命令用于更新功能代码:
aws lambda update-function-code \ --function-name HelloCouchbaseLambda \ --zip-file fileb:///Users/arungupta/workspaces/serverless/aws/hellocouchbase/hellocouchbase/target/hellocouchbase-1.0-SNAPSHOT.jar \ --region us-west-2 \ --publish
显示结果:
{ "CodeSha256": "w510ejw/OoVsQt2JiLG2bPZPAaFvQCRrYYYlQWctCQE=", "FunctionName": "HelloCouchbaseLambda", "CodeSize": 6978108, "MemorySize": 1024, "FunctionArn": "arn:aws:lambda:us-west-2:<account-id>:function:HelloCouchbaseLambda:8", "Environment": { "Variables": { "COUCHBASE_HOST": "ec2-35-165-249-235.us-west-2.compute.amazonaws.com" } }, "Version": "8", "Role": "arn:aws:iam::<account-id>:role/service-role/myLambdaRole", "Timeout": 30, "LastModified": "2016-12-25T04:17:38.717+0000", "Handler": "org.sample.serverless.aws.couchbase.HelloCouchbaseLambda", "Runtime": "java8", "Description": "Java Hello Couchbase" }
然后可以再次调用该函数。
在写这篇博客的过程中,这也经常被用来调试功能。这是因为 Lambda 函数没有任何关联的状态或框。因此,您无法登录到一个盒子来检查该功能是否未正确部署。一旦功能正常运行,您当然可以使用 CloudWatch 日志语句。
标签2: Java教程地址:https://www.cundage.com/article/jcg-serverless-faas-aws-lambda-java.html