什么是无服务器架构?
无服务器架构在由第三方完全管理的临时容器中运行自定义代码。 自定义代码通常只是完整应用程序的一小部分。 也称为函数 。 这为无服务器架构提供了另一个名称,即功能即服务 (FaaS)。 该容器是短暂的,因为它只能持续一次调用。 容器可以重复使用,但这不是您可以依赖的东西。 作为开发人员,您将代码上传到FaaS平台,然后该服务处理基础结构的所有容量,扩展,修补和管理,以运行您的代码。
使用无服务器架构构建的应用程序遵循事件驱动方法。 例如,应用程序中发生了诸如点击之类的活动。
这与经典体系结构非常不同,在经典体系结构中,通常将应用程序代码部署在Tomcat或WildFly等应用服务器中。 扩展应用程序意味着启动应用程序服务器的其他实例或使用打包的应用程序服务器扩展其他容器。 负载均衡器需要使用新的IP地址进行更新。 操作系统需要打补丁,升级和维护。
无服务器架构解释了经典编程模型与这种新的无服务器架构之间的区别。
FaaS平台将您的应用程序划分为多个功能。 每个功能都部署在FaaS中。 该服务启动其他计算实例,以满足您的应用程序的可伸缩性需求。 FaaS平台提供了执行环境,并负责启动和拆除容器以运行您的功能。
阅读无服务器架构,以获取有关这些映像的更多详细信息。
FaaS的一大优点是,您只需为计算时间付费,即代码运行的时间。 代码未运行时不收费。
查看功能与VM和容器有何不同的另一种方式:
请注意,Linux容器而非Docker容器被用作AWS Lambda的实现。
FaaS与PaaS有何不同?
如无服务器架构所引用,以下推文提供了快速答案:
如果您的PaaS可以在20毫秒内有效地启动实例并运行半秒,则将其称为无服务器。 https://t.co/S3YzvqFYLR
— adrian cockcroft(@adrianco) 2016年5月28日
换句话说,大多数PaaS应用程序都不适合针对每个请求上下移动整个应用程序,而FaaS平台正是这样做的。
使用FaaS抽象化后端说明了不同* aaS产品的区别。 博客中的图像如下所示:
无服务器架构还提供了关于什么是FaaS和不是FaaS的详细信息。
AWS Lambda , Google Cloud Functions和Azure Functions是运行无服务器应用程序的一些选项。
该博客将展示如何编写您的第一个AWS Lambda函数。
什么是AWS Lambda?
AWS Lambda是Amazon Web Services的FaaS服务。 它在高可用性计算基础架构上运行您的代码,并执行所有计算资源管理,包括服务器和操作系统维护,容量配置和自动伸缩,代码监视和日志记录。
在代码运行期间,AWS Lambda向您收费(以100ms为增量)。 将Lambda函数存储在AWS中没有任何成本。 每月前一百万个请求是免费的,之后的价格是名义上的。 阅读有关Lambda定价的更多详细信息。 它还通过向AWS CloudWatch提供实时指标和日志来提供对性能的可见性。 您需要做的就是编写代码!
快速介绍:
还要从AWS ReInvent 2016中检查AWS Lambda的新增功能:
还要从AWS ReInvent 2016中检出无服务器架构模式和最佳实践:
您在AWS Lambda上运行的代码称为Lambda函数。 您可以将代码作为zip文件上传或使用AWS Lambda管理控制台进行设计 。 AWS SDK内置了支持,这简化了调用其他AWS服务的能力。
简而言之,Lambda是可扩展的,无服务器的云计算。
AWS Lambda提供了几种执行环境:
- Node.js – v0.10.36,v4.3.2(推荐)
- Java – Java 8
- Python – Python 2.7
- .NET Core – .NET Core 1.0.1(C#)
该博客将显示:
- 构建一个将JSON文档存储到Couchbase的Java应用程序
- 使用Maven创建Java应用程序的部署包
- 创建Lambda函数
- 更新Lambda函数
该博客中的完整代码可在github.com/arun-gupta/serverless/tree/master/aws/hellocouchbase中找到 。
适用于AWS Lambda的Java应用程序
首先,让我们看一下将用于此Lambda函数的Java应用程序。 Java Lambda函数编程模型提供了有关如何用Java编写Lambda函数代码的更多详细信息。
我们的Lambda函数将实现预定义的接口com.amazonaws.services.lambda.runtime.RequestHandler
。 代码如下:
public class HelloCouchbase implements RequestHandler {
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集群的主要入口点。 创建Lambda函数时,将传递COUCHBASE_HOST
环境变量。 在我们的案例中,这将指向在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部署程序包
AWS Lambda函数需要部署程序包。 该软件包是一个.zip
或.jar
文件,其中包含该函数的所有依赖关系。 我们的应用程序是使用Maven打包的,因此我们将使用Maven插件来创建部署包。
该应用程序具有pom.xml
和以下插件片段:
org.apache.maven.plugins
maven-shade-plugin
2.3
false
package
shade
有关在没有任何IDE的情况下使用Maven创建.jar部署程序包的详细信息,请参见Maven配置。 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 Lambda函数
使用AWS CLI创建AWS Lambda函数。 在这种情况下,CLI命令如下所示:
aws lambda create-function \
--function-name HelloWorld \
--role arn:aws:iam:::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 Console执行Lambda函数,则将为您创建此角色。 -
--zip-file
指向在上一步中创建的部署包。fileb
是AWS CLI特定的协议,用于指示上传的内容是二进制的。 -
--handler
是开始执行功能的Java类 -
--publish
请求AWS Lambda创建Lambda函数并将其版本发布为原子操作。 否则,可能会创建多个版本,并可能在以后发布。
Lambda控制台显示:
测试AWS 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\"}"
调用此函数会将JSON文档存储在Couchbase中。 可以使用Couchbase Web Console查看存储在Couchbase中的文档。 密码为Administrator
,密码为EC2实例ID。
该Couchbase实例中的所有数据存储区如下所示:
请注意, serverless
存储桶是手动创建的。
单击文档显示存储在存储桶中的不同文档的详细信息:
单击每个文档将显示有关JSON文档的更多详细信息:
Lambda函数也可以使用控制台进行测试:
更新AWS 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::function:HelloCouchbaseLambda:8",
"Environment": {
"Variables": {
"COUCHBASE_HOST": "ec2-35-165-249-235.us-west-2.compute.amazonaws.com"
}
},
"Version": "8",
"Role": "arn:aws:iam:::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日志语句。
AWS Lambda参考
- 无服务器架构
- AWS Lambda:工作原理
- Couchbase服务器文档
- Couchbase论坛
- 在@couchbasedev上关注我们
翻译自: https://www.javacodegeeks.com/2016/12/serverless-faas-aws-lambda-java.html