标签 无服务器 下的文章

在 Kubernetes 中运行无服务器函数时,实现更快的启动速度和更小的内存占用。

 title=

由于运行上千个应用程序 容器荚 Pod 所耗费的资源多,令它实现较少工作节点和资源占用所需成本也较高,所以在使用 Kubernetes 时,快速启动和较少的内存占用是至关重要的。在 Kubernetes 平台运行容器化微服务时,内存占用是比吞吐量更重要的考量因素,这是因为:

  • 由于需要持续运行,所以耗费资源更多(不同于 CPU 占用)
  • 微服务令开销成本成倍增加
  • 一个单体应用程序变为若干个微服务的情况(例如 20 个微服务占用的存储空间约有 20GB)

这些情况极大影响了无服务器函数的发展和 Java 部署模型。到目前为止,许多企业开发人员选择 Go、Python 或 Node.js 这些替代方案来解决性能瓶颈,直到出现了 Quarkus 这种基于 kubernetes 的原生 Java 堆栈,才有所改观。本文介绍如何在使用了 Quarkus 的 kubernetes 平台上进行性能优化,以便运行无服务器函数。

容器优先的设计理念

由于 Java 生态系统中传统的框架都要进行框架的初始化,包括配置文件的处理、classpath 的扫描、类加载、注解的处理以及构建元模型,这些过程都是必不可少的,所以它们都比较耗费资源。如果使用了几种不同的框架,所耗费的资源也是成倍增加。

Quarkus 通过“ 左移 shifting left ”,把所有的资源开销大的操作都转移到构建阶段,解决了这些 Java 性能问题。在构建阶段进行代码和框架分析、字节码转换和动态元模型生成,而且只有一次,结果是:运行时可执行文件经过高度优化,启动非常快,不需要经过那些传统的启动过程,全过程只在构建阶段执行一次。

 title=

更重要的是:Quarkus 支持构建原生可执行文件,它具有良好性能,包括快速启动和极小的 驻留集大小 resident set size (RSS)内存占用,跟传统的云原生 Java 栈相比,具备即时扩展的能力和高密度的内存利用。

 title=

这里有个例子,展示如何使用 Quarkus 将一个 Java 无服务器 项目构建为本地可执行文件。

1、使用 Quarkus 创建无服务器 Maven 项目

以下命令生成一个 Quarkus 项目,(例如 quarkus-serverless-native)以此创建一个简单的函数:

$ mvn io.quarkus:quarkus-maven-plugin:1.13.4.Final:create \
       -DprojectGroupId=org.acme \
       -DprojectArtifactId=quarkus-serverless-native \
       -DclassName="org.acme.getting.started.GreetingResource"

2、构建一个本地可执行文件

你需要使用 GraalVM 为 Java 程序构建一个本地可执行文件。你可以选择 GraalVM 的任何发行版,例如 Oracle GraalVM Community Edition (CE)Mandrel(Oracle GraalVM CE 的下游发行版)。Mandrel 是为支持 OpenJDK 11 上的 Quarkus-native 可执行文件的构建而设计的。

打开 pom.xml,你将发现其中的 native 设置。你将使用它来构建本地可执行文件。

<profiles>
    <profile>
        <id>native</id>
        <properties>
            <quarkus.package.type>native</quarkus.package.type>
        </properties>
    </profile>
</profiles>
注意: 你可以在本地安装 GraalVM 或 Mandrel 发行版。你也可以下载 Mandrel 容器映像来构建它(像我那样),因此你还需要在本地运行一个容器引擎(例如 Docker)。

假设你已经打开了容器运行时,此时需要运行一下 Maven 命令:

使用 Docker 作为容器引擎:

$ ./mvnw package -Pnative \
  -Dquarkus.native.container-build=true \
  -Dquarkus.native.container-runtime=docker

使用 Podman 作为容器引擎:

$ ./mvnw package -Pnative \
  -Dquarkus.native.container-build=true \
  -Dquarkus.native.container-runtime=podman

输出信息结尾应当是 BUILD SUCCESS

 title=

不借助 JVM 直接运行本地可执行文件:

$ target/quarkus-serverless-native-1.0.0-SNAPSHOT-runner

输出信息类似于:

__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \  
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/  
INFO  [io.quarkus] (main) quarkus-serverless-native 1.0.0-SNAPSHOT native
(powered by Quarkus xx.xx.xx.) Started in 0.019s. Listening on: http://0.0.0.0:8080
INFO [io.quarkus] (main) Profile prod activated.
INFO [io.quarkus] (main) Installed features: [cdi, kubernetes, resteasy]

简直是超音速!启动只花了 19 毫秒。你的运行时间可能稍有不同。

使用 Linux 的 ps 工具检测一下,结果内存占用还是很低。检测的方法是:在应用程序运行期间,另外打开一个终端,运行如下命令:

$ ps -o pid,rss,command -p $(pgrep -f runner)

输出结果类似于:

  PID    RSS COMMAND
10246  11360 target/quarkus-serverless-native-1.0.0-SNAPSHOT-runner

该进程只占 11MB 内存。非常小!

注意: 各种应用程序(包括 Quarkus)的驻留集大小和内存占用,都因运行环境而异,并随着应用程序载入而上升。

你也可以使用 REST API 访问这个函数。输出结果应该是 Hello RESTEasy:

$ curl localhost:8080/hello
Hello RESTEasy

3、把函数部署到 Knative 服务

如果你还没有创建命名空间,现在就在 OKD(OpenShift Kubernetes 发行版)创建一个命名空间(例如 quarkus-serverless-native),进而把这个本地可执行文件部署为无服务器函数。然后添加 quarkus-openshift 扩展:

$ ./mvnw -q quarkus:add-extension -Dextensions="openshift"

src/main/resources/application.properties 文件中添加以下内容,配置 Knative 和 Kubernetes 的相关资源:

quarkus.container-image.group=quarkus-serverless-native
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000
quarkus.native.container-build=true
quarkus.kubernetes-client.trust-certs=true
quarkus.kubernetes.deployment-target=knative
quarkus.kubernetes.deploy=true
quarkus.openshift.build-strategy=docker

构建本地可执行文件,并把它直接部署到 OKD 集群:

$ ./mvnw clean package -Pnative
注意: 提前使用 oc login 命令,确保登录的是正确的项目(例如 quarkus-serverless-native)。

输出信息结尾应当是 BUILD SUCCESS。完成一个本地二进制文件的构建并部署为 Knative 服务需要花费几分钟。成功创建服务后,使用 kubectloc 命令工具,可以查看 Knative 服务和版本信息:

$ kubectl get ksvc
NAME                        URL   [...]
quarkus-serverless-native   http://quarkus-serverless-native-[...].SUBDOMAIN  True

$ kubectl get rev
NAME                              CONFIG NAME                 K8S SERVICE NAME                  GENERATION   READY   REASON
quarkus-serverless-native-00001   quarkus-serverless-native   quarkus-serverless-native-00001   1            True

4、访问本地可执行函数

运行 kubectl 命令,搜索无服务器函数的节点:

$ kubectl get rt/quarkus-serverless-native

输出信息类似于:

NAME                         URL                                                                                                          READY   REASON
quarkus-serverless-native   http://quarkus-serverless-restapi-quarkus-serverless-native.SUBDOMAIN   True

curl 命令访问上述信息中的 URL 字段:

$ curl http://quarkus-serverless-restapi-quarkus-serverless-native.SUBDOMAIN/hello

过了不超过一秒钟,你也会得到跟本地操作一样的结果:

Hello RESTEasy

当你在 OKD 群集中访问 Quarkus 运行中的节点的日志,你会发现本地可执行文件正在以 Knative 服务的形式运行。

 title=

下一步呢?

你可以借助 GraalVM 发行版优化 Java 无服务器函数,从而在 Knative 中使用 Kubernetes 将它们部署为无服务器函数。Quarkus 支持在普通的微服务中使用简易配置进行性能优化。

本系列的下一篇文章将指导你在不更改代码的情况下跨多个无服务器平台实现可移植函数。

(Daniel Oh, CC BY-SA 4.0)


via: https://opensource.com/article/21/6/java-serverless-functions-kubernetes

作者:Daniel Oh 选题:lujun9972 译者:cool-summer-021 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Quarkus 令你可以使用类似 Java 的技术开发无服务器的工作负载。

无服务器 Java 的研究始于函数 —— 就是按需求运行的一小段代码。这一阶段并没有持续很长时间。虽然在 1.0 阶段,基于虚拟机架构的函数使这种范式变得很流行,但它仍然有局限性,例如执行时间、协议和糟糕的本地开发体验,都不太理想,如下图所示。

开发者随后意识到,可以把同样的无服务器特性应用于微服务和 Linux 容器,带来的好处也是一样的。由此进入 1.5 阶段,在这个阶段,一些无服务器容器完全抽象化了 Kubernetes,通过 Knative 或其它位于它之上的抽象层来提供无服务器的体验。

在 2.0 阶段,无服务器开始处理更复杂的编排和集成模式,并结合某些层级的状态管理。更重要的是,开发者关注的是能否在旧的系统中使用熟悉的 Java 应用程序运行时来组合运行无服务器和非无服务器的工作负载。

The serverless Java journey

Java 开发者开始进行无服务器函数开发之前,第一步是要选择一种新的云原生 Java 框架,从而能够以快于传统单体应用程序的速度和较小的内存占用运行 Java 函数。这在各种基础设施环境中,包括物理服务器、虚拟机、多云或混合云环境中的容器,都是适用的。

开发者也有可能固执地选择 Spring 框架中的 Spring 云函数 来进行命令式和反应式函数的开发。Spring 也支持将 Java 函数部署到可安装的无服务器平台,比如 KubelessApache OpenWhiskFissionProject Riff。然而,人们担心 Spring 的启动慢、响应时间长以及内存占用大的问题。在诸如 Kubernetes 这种可扩展的容器环境中运行 Java 函数,这些问题可能会更严重。

Quarkus 是一个新推出的开源云原生 Java 框架,它有助于解决这些问题。它的作用是设计无服务器应用程序,以及编写运行于云基础设施(例如 Kubernetes)的云原生微服务。

Quarkus 重新审视了 Java,它使用了封闭的方法构建和运行 Java 程序。它把 Java 转变为一种可与 Go 相媲美的运行时。Quarkus 也包含 100 多种扩展功能,集成了企业级能力,例如数据库访问、无服务器集成、消息、安全、可观察性和业务自动化。

这里有一个简单例子,展现如何使用 Quarkus 创建一个 Java 无服务器项目的框架。

1、基于 Maven 创建一个 Quarkus 无服务器项目

安装一个本地 Kubernetes 集群,开发者有多种选择,包括 MinikubeOKD。因为使用 OKD 在 Knative 和 DevOps 工具上安装无服务器相关功能较方便,本文使用 OKD 安装集群。这些关于 OKD 安装Knative 操作员安装 的相关指南中提供了更多的设置资料。

下面的命令创建了一个 Quarkus 项目(例如 quarkus-serverless-restapi),对外暴露一个简单的 REST API,并下载 quarkus-openshift 扩展,用于 Knative 服务的部署:

$ mvn io.quarkus:quarkus-maven-plugin:1.13.4.Final:create \
       -DprojectGroupId=org.acme \
       -DprojectArtifactId=quarkus-serverless-restapi \
       -Dextensions="openshift" \
       -DclassName="org.acme.getting.started.GreetingResource"

2、在本地运行无服务器功能

使用 Quarkus 开发模式运行程序,检查 REST API 是否有效,稍稍调整一下代码:

$ ./mvnw quarkus:dev

输出如下内容:

__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
INFO  [io.quarkus] (Quarkus Main Thread) quarkus-serverless-restapi 1.0.0-SNAPSHOT on JVM (powered by Quarkus xx.xx.xx.) started in 2.386s. Listening on: http://localhost:8080
INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, kubernetes, resteasy]
注意: 保持 Quarkus 应用程序运行,需要使用 热部署 Live Coding 。这样,当代码修改后,你就不必重新构建、重新部署以及重启运行时。

现在,你可以使用一个 curl 命令快速访问 REST API。输出结果应当是 Hello RESTEasy:

$ curl localhost:8080/hello
Hello RESTEasy

GreetingResource.java 中修改返回值:

public String hello() {
        return "Quarkus Function on Kubernetes";
    }

再次访问 REST API,输出信息也会相应更新:

$ curl localhost:8080/hello
Quarkus Function on Kubernetes

普通的微服务跟无服务器函数之间的差别并不大。使用 Quarkus 的好处在于:开发者可以使用任何微服务,将 Kubernetes 部署为无服务器函数。

3、在 Knative 服务中部署相关的函数

如果你还没有创建命名空间,就在你的 OKD 集群上 创建命名空间(例如 quarkus-serverless-restapi),用来部署 Java 无服务器函数。

Quarkus 令开发者可以通过在 src/main/resources/application.properties 中添加以下变量,创建 Knative 和 Kubernetes 资源:

quarkus.container-image.group=quarkus-serverless-restapi <1>
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000 <2>
quarkus.kubernetes-client.trust-certs=true <3>
quarkus.kubernetes.deployment-target=knative <4>
quarkus.kubernetes.deploy=true <5>
quarkus.openshift.build-strategy=docker <6>

说明:

  • <1> 在你部署无服务器应用程序的位置定义项目名
  • <2> 使用容器注册中心
  • <3> 在这个简单例子中,使用自签名证书,以便通过相关信任机制
  • <4> 允许创建 Knative 资源
  • <5> 指示在构建容器映像之后将扩展部署到 OpenShift
  • <6> 设置 Docker 构建策略

执行以下命令,构建应用程序,并直接部署到 OKD 集群:

$ ./mvnw clean package -DskipTests
注意: 应该提前使用 oc login 命令,确保登录到正确的项目(例如quarkus-serverless-restapi)。

输出结果应该以 BUILD SUCCESS 结束。

在对于 Knative 服务执行的 oc 命令中,加上标签:

$ oc label rev/quarkus-serverless-restapi-00001 
app.openshift.io/runtime=quarkus --overwrite

然后访问 OKD 网页控制台,就能进入 开发人员透视图中的拓扑视图。你可能会看到你的 容器荚 Pod (无服务器函数)已经缩小为零(白线圈)。

Topology view

4、在 Kubernetes 环境下测试函数

运行如下 oc 命令,搜索含有无服务器函数的路由:

$ oc get rt/quarkus-serverless-restapi
[...]
NAME                      URL                             READY   REASON
quarkus-serverless[...]   http://quarkus[...].SUBDOMAIN   True

使用 curl 命令访问搜索到的路由:

$ curl http://quarkus-serverless-restapi-quarkus-serverless-restapi.SUBDOMAIN/hello

过几秒钟,你可以得到跟在本地相同的结果:

Quarkus Function on Kubernetes

当你回到 OKD 集群内的拓扑图,Knative 服务会自动扩展。

Scaling the Knative Function

由于 Knative 服务的默认设置,其 pod 在 30 秒后会再次下降至零。

下一步呢?

无服务器不断地在演变,始于运行于虚拟机的函数,到后来的无服务器容器,并与企业原有系统集成。在此过程中,企业开发者借助 Quarkus,仍然可以使用自己熟悉的技术(比如 Java)创建一个项目,然后构建并部署到 Kubernetes。

本系列的下一篇文章将指导你优化 Kubernetes 中的 Java 无服务器函数,从而令程序启动更快,内存占用更小。

文内图像来自:Daniel Oh, CC BY-SA 4.0


via: https://opensource.com/article/21/6/java-serverless-functions

作者:Daniel Oh 选题:lkxed 译者:cool-summer-021 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

无服务器计算将服务器从规划中移除,使企业能够专注于应用功能。那么,企业是不是都应该选择无服务器计算呢?让我们来探究一下吧!

直至不久之前,几乎每个产品经理都会将他/她的工程资源,分成两个独立的团队 —— 开发团队和运维团队。开发团队通常参与编码、测试和构建应用功能,而运维团队负责应用程序的交付、部署和运行维护。

当开发团队构建电商应用时,运维团队会搭建好服务器来托管该应用。搭建服务器涉及到许多方面,其中包括:

  • 选择合适的硬件和操作系统
  • 应用所需的补丁集
  • 搭建所需服务器环境,如 JDK、Python、Tomcat、NodeJS 等
  • 部署、配置和提供实际的应用
  • 打开并固定合适的端口
  • 搭建所需的数据库引擎

……这个名单还在继续。

除此之外,管理人员还对容量规划感到头疼。毕竟,任何重要应用都应始终保持 100% 可用、可靠且可扩展。这需要对硬件进行最佳投资。众所周知,在一些关键时期,硬件短缺会导致业务损失,而硬件冗余又会损害利润。因此,无论应用是针对本地数据中心,还是针对云基础架构,容量规划都是至关重要的。到目前为止,很明显,企业不仅在功能构建上投入了大量的精力,还在功能交付上也花费了大量的时间。

无服务器计算 Serverless computing 旨在提供一种无缝的方式来交付功能,而无需担心服务器的设置和维护。换句话说,无服务器计算平台提供了一个“ 即用型 ready-to-use ”环境,企业可以尽快将应用程序构建和部署为一些较小的功能。这就是为什么这种方法被称为“ 功能即服务 Function as a Service ”(FaaS)。

请记住,无服务器计算中仍然存在服务器,但它由 AWS、微软和谷歌等 FaaS 供应商负责。

例如,AWS 以 “Lambda 函数”的形式提供了一个无服务器计算环境。开发人员可以选择将应用程序构建为一组 Lambda 函数,这些函数可以用 NodeJS、Java、Python 和其他一些语言编写。AWS 提供了一个现成的环境来部署这些函数。它还提供了即用​​型数据库服务器、文件服务器、应用程序网关和身份验证服务器等。

同样,微软 Azure 也提供了一个环境,它可以用 C# 等语言构建和部署 Azure 函数。

为什么选择无服务器?

有两个主要因素推动了无服务器计算的普及。

1、即用型环境

显然,这是无服务器计算的最大卖点。企业无需提前采购/预订硬件或实例,也无需操心许可证,以及设置和配置服务器。他们不需要为扩大和缩小规模而烦恼。所有这些都由 FaaS 供应商负责。

2、最优成本

由于 FaaS 供应商总是根据环境的利用率向客户收费(按使用付费模式),因此企业无需担心前期成本和资源浪费。例如,AWS 根据 Lambda 函数接收的请求数量、在数据表上运行的查询数量等指标来向客户端收费。

无服务器计算的挑战

与任何其他方法一样,无服务器计算也不是每个人都可以盲目遵循的完美方法。它本身也有一系列限制。以下是其中的几个。

1、供应商锁定

当使用无服务器计算时,第一个也是最重要的问题就是,Lambda 或 Azure 等函数将使用供应商提供的 API 来编写。例如,使用 AWS Lambda API 编写的函数无法部署到 Google Cloud 中,反之亦然。因此,无服务器计算迫使企业在许多年内,只能使用同一家供应商。并且,应用的成功或失败不仅取决于它的功能,还取决于供应商在性能等方面的能力。

2、编程语言

没有哪家无服务器计算平台支持所有的编程语言。此外,对于它支持的编程语言,它也可能不支持其所有版本。这样一来,应用开发团队只能选择供应商提供的语言。就团队的能力而言,这可能是非常关键的。

3、最优成本,真的吗?

其实也不一定,这一切都取决于资源的使用情况。如果你的应用正在承受巨大的负载,例如每秒数百万个请求,那么你所支付的费用可能会过高。在这样的规模下,在本地或云端拥有自己的服务器可能会更便宜。这并不意味着具有 Web 规模的应用不适合用无服务器计算。归根结底,它还是取决于你的平台的构建方式,以及你与供应商签署的协议。

4、生态系统

没有哪个应用是为了一个孤立的环境而编写的。它总是需要其他组件,如数据存储、数据库、安全引擎、网关、消息服务器、队列、缓存等。每个平台都提供自己的一组此类工具。例如,AWS 提供了 Dynamo DB 作为其 NoSQL 解决方案之一。显然,其他供应商也提供了自己的 NoSQL 解决方案。因此,团队又会被迫地基于所选平台来构建应用程序。尽管大多数商业 FaaS 供应商都为特定需求提供了多个组件,但并非每个组件都可能是同类型中最佳的。

为什么不考虑容器呢?

在过去十年中,我们中的许多人都迁移到了容器化部署模型,因为它们为昂贵的物理机或虚拟机提供了一种轻量级的替代方案。有了 Kubernetes 等编排工具后,我们乐于部署容器化应用,同时也满足了 Web 规模的要求。容器提供了与底层环境一定程度的隔离,这使得部署相对容易。但是,我们仍然需要在硬件(本地或云)、许可证、网络、配置等方面进行投资,这需要具有前瞻性的规划、合适的技术能力和仔细的监控。无服务器计算,尽管它也有自己的优点和缺点,但它让我们把这些责任也摆脱了。

展望未来

我们正处于持续开发、持续集成和持续部署的时代。每个企业都面临着竞争。产品 上市时间 Time to market (TTM)在吸引客户、留住客户这两个方面,发挥着重要作用。在这种背景下,企业喜欢花更多时间来尽可能快地推出功能,而不是在部署和维护的细节上苦苦挣扎。无服务器计算有可能满足这些需求。大玩家们正在投入巨额资金,以使 FaaS 尽可能地无缝且经济。无服务器计算的未来看起来是一片光明。


via: https://www.opensourceforu.com/2021/12/should-businesses-opt-for-serverless-computing/

作者:Krishna Mohan Koyya 选题:lkxed 译者:lkxed 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Java 仍是开发企业应用程序最流行的语言之一。那么,为什么 无服务器 serverless 开发人员对它望而却步?

 title=

几十年来,企业已经在各类平台上开发了关键业务应用程序,包括物理服务器、虚拟机和云环境。这些应用程序在各行各业都有一个共同点,那就是无论需求如何,它们都需要持续可用(24x7x365),保证稳定性、可靠性和性能。因此,即使实际资源利用率低于 50%,每个企业都必须付出高额成本维护基础架构(如 CPU、内存、磁盘、网络等)。

无服务器架构是为了帮助解决这些问题而产生的。无服务器允许开发人员按需构建和运行应用程序,保证高可用性,不必在多云和混合云环境中管理服务器。在幕后,无服务器拓扑中仍有很多服务器,但它们是从应用程序开发中抽象出来的。相反,云提供商使用无服务器进行资源管理,例如配置、维护、联网和扩展服务器实例。

由于其高效性,无服务器开发模式现在是一些企业的需求,这些企业希望按需启动服务,而不是一直运行服务。

许多新建的开源项目用来在 Kubernetes 集群上通过 Linux 容器包来管理无服务器应用程序。CNCF 的《交互式无服务器全景》 是一份关于开源项目、工具、框架和公共云平台的指南,帮助 DevOps 团队处理无服务器应用程序。

 title=

开发人员可以编写代码,然后将其快速部署到各种无服务器环境中。然后,无服务器应用程序响应需求,并根据需要自动伸缩扩展。

你可能想知道什么编程语言和运行环境最适合无服务器应用程序开发,以便与上图中的技术集成。这个问题不只一个答案,但是让我们退一步来讨论在企业生产环境中开发业务应用程序最流行的应用程序运行环境:Java。

Developer Economics 称,截至 2020 年第三季度,仍有 800 多万家企业开发人员在使用 Java 来实现其业务需求。然而,根据 2020 年的一项调查,Java(占比 6%)显然不是有前瞻意识的开发人员的首选,他们使用当前云服务做开发。

 title=

来自 NewRelic 无服务器基准报告的数据(Daniel Oh, CC BY-SA 4.0

资源使用、响应时间和延迟在无服务器开发中至关重要。公有云提供商提供的无服务器产品通常是按需计量的,只有在无服务器应用程序启动时,才会通过事件驱动的执行模式收费。因此,当无服务器应用程序闲置或缩减为零时,企业无需支付任何费用。

带有容器的 Java 状态

在这种背景下,你可能会问:“既然现有业务应用程序很可能是在 Java 技术上开发的,那么开发人员为什么不尝试使用 Java 栈进行无服务器应用程序开发呢?

隐藏的真相是:很难在新的不可变更的基础设施(例如 Kubernetes 这样的容器平台)中优化 Java 应用程序。

 title=

该图描述了 Java 进程与竞争的语言、框架(如 Node.jsGo)之间内存资源使用的差异。Java HotSpot 占用资源最大,其中包括每个 Java 虚拟机 Java Virtual Machine (JVM)实例分配的堆内存。中间显示了 Node.js 每个进程要比 Java 小得多。最后,Go 是一种流行的云服务编程语言,因为它的内存消耗最低。

如你所见,当你在这张图从左到右走,你会看到更密的节点。这就是开发人员在云、容器和 Kubernetes 上编写无服务器应用程序时回避 Java(包括 Spring Boot,一种顽固的微服务 Java 框架)的原因。

下一步是什么?

企业可以通过实现无服务器应用程序获得明显的好处,但是资源密度问题导致他们避免使用 Java 堆栈在 Kubernetes 上开发无服务器应用程序开发。但是选择其他语言会给全球数百万 Java 开发人员带来学习负担。因此,在本系列的下一篇文章中,我将指导你如何开始使用 Java 无服务器函数,而不是使用其他语言。


via: https://opensource.com/article/21/5/what-serverless-java

作者:Daniel Oh 选题:lujun9972 译者:DCOLIVERSUN 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

我在 $work 建立了一个基于 Kubernetes 的平台已经快一年了,而且有点像 Kubernetes 的布道者了。真的,我认为这项技术太棒了。然而我并没有对它的运营和维护的困难程度抱过什么幻想。今年早些时候我读了这样的一篇文章,并对其中某些观点深以为然。如果我在一家规模较小的、有 10 到 15 个工程师的公司,假如有人建议管理和维护一批 Kubernetes 集群,那我会感到害怕的,因为它的运维开销太高了!

尽管我现在对 Kubernetes 的一切都很感兴趣,但我仍然对“ 无服务器 Serverless ”计算会消灭运维工程师的说法抱有好奇。这种好奇心主要来源于我希望在未来仍然能有一份有报酬的工作 —— 如果我们前景光明的未来不需要运维工程师,那我得明白到底是怎么回事。我已经在 Lamdba 和Google Cloud Functions 上做了一些实验,结果让我印象十分深刻,但我仍然坚信无服务器解决方案只是解决了一部分问题。

我关注 AWS Fargate 已经有一段时间了,这就是 $work 的开发人员所推崇为“无服务器计算”的东西 —— 主要是因为 Fargate,用它你就可以无需管理底层节点而运行你的 Docker 容器。我想看看它到底意味着什么,所以我开始尝试从头开始在 Fargate 上运行一个应用,看看是否可以成功。这里我对成功的定义是一个与“生产级”应用程序相近的东西,我想应该包含以下内容:

  • 一个在 Fargate 上运行的容器
  • 配置信息以环境变量的形式下推
  • “秘密信息” 不能是明文的
  • 位于负载均衡器之后
  • 有效的 SSL 证书的 TLS 通道

我以“基础设施即代码”的角度来开始整个任务,不遵循默认的 AWS 控制台向导,而是使用 terraform 来定义基础架构。这很可能让整个事情变得复杂,但我想确保任何部署都是可重现的,任何想要遵循此步骤的人都可发现我的结论。

上述所有标准通常都可以通过基于 Kubernetes 的平台使用一些外部的附加组件和插件来实现,所以我确实是以一种比较的心态来处理整个任务的,因为我要将它与我的常用工作流程进行比较。我的主要目标是看看Fargate 有多容易,特别是与 Kubernetes 相比时。结果让我感到非常惊讶。

AWS 是有开销的

我有一个干净的 AWS 账户,并决定从零到部署一个 webapp。与 AWS 中的其它基础设施一样,我必须首先使基本的基础设施正常工作起来,因此我需要先定义一个 VPC。

遵循最佳实践,因此我将这个 VPC 划分为跨可用区(AZ)的子网,一个公共子网和私有子网。这时我想到,只要这种设置基础设施的需求存在,我就能找到一份这种工作。AWS 是免运维的这一概念一直让我感到愤怒。开发者社区中的许多人理所当然地认为在设置和定义一个设计良好的 AWS 账户和基础设施是不需要付出多少工作和努力的。而这种想当然甚至发生在开始谈论多帐户架构之前就有了——现在我仍然使用单一帐户,我已经必须定义好基础设施和传统的网络设备。

这里也值得记住,我已经做了很多次,所以我很清楚该做什么。我可以在我的帐户中使用默认的 VPC 以及预先提供的子网,我觉得很多刚开始的人也可以使用它。这大概花了我半个小时才运行起来,但我不禁想到,即使我想运行 lambda 函数,我仍然需要某种连接和网络。定义 NAT 网关和在 VPC 中路由根本不会让你觉得很“Serverless”,但要往下进行这就是必须要做的。

运行简单的容器

在我启动运行了基本的基础设施之后,现在我想让我的 Docker 容器运行起来。我开始翻阅 Fargate 文档并浏览 入门 文档,这些就马上就展现在了我面前:

等等,只是让我的容器运行就至少要有三个步骤?这完全不像我所想的,不过还是让我们开始吧。

任务定义

任务定义 Task Definition ”用来定义要运行的实际容器。我在这里遇到的问题是,任务定义这件事非常复杂。这里有很多选项都很简单,比如指定 Docker 镜像和内存限制,但我还必须定义一个网络模型以及我并不熟悉的其它各种选项。真需要这样吗?如果我完全没有 AWS 方面的知识就进入到这个过程里,那么在这个阶段我会感觉非常的不知所措。可以在 AWS 页面上找到这些 参数 的完整列表,这个列表很长。我知道我的容器需要一些环境变量,它需要暴露一个端口。所以我首先在一个神奇的 terraform 模块 的帮助下定义了这一点,这真的让这件事更容易了。如果没有这个模块,我就得手写 JSON 来定义我的容器定义。

首先我定义了一些环境变量:

container_environment_variables = [
    {
      name  = "USER"
      value = "${var.user}"
    },
    {
      name  = "PASSWORD"
      value = "${var.password}"
    }
]

然后我使用上面提及的模块组成了任务定义:

module "container_definition_app" {
  source  = "cloudposse/ecs-container-definition/aws"
  version = "v0.7.0"

  container_name  = "${var.name}"
  container_image = "${var.image}"

  container_cpu                = "${var.ecs_task_cpu}"
  container_memory             = "${var.ecs_task_memory}"
  container_memory_reservation = "${var.container_memory_reservation}"

  port_mappings = [
    {
      containerPort = "${var.app_port}"
      hostPort      = "${var.app_port}"
      protocol      = "tcp"
    },
  ]

  environment = "${local.container_environment_variables}"

}

在这一点上我非常困惑,我需要在这里定义很多配置才能运行,而这时什么都没有开始呢,但这是必要的 —— 运行 Docker 容器肯定需要了解一些容器配置的知识。我 之前写过 关于 Kubernetes 和配置管理的问题的文章,在这里似乎遇到了同样的问题。

接下来,我在上面的模块中定义了任务定义(幸好从我这里抽象出了所需的 JSON —— 如果我不得不手写JSON,我可能已经放弃了)。

当我定义模块参数时,我突然意识到我漏掉了一些东西。我需要一个 IAM 角色!好吧,让我来定义:

resource "aws_iam_role" "ecs_task_execution" {
  name = "${var.name}-ecs_task_execution"

  assume_role_policy = <<EOF
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "ecs_task_execution" {
  count = "${length(var.policies_arn)}"

  role       = "${aws_iam_role.ecs_task_execution.id}"
  policy_arn = "${element(var.policies_arn, count.index)}"
}

这样做是有意义的,我需要在 Kubernetes 中定义一个 RBAC 策略,所以在这里我还未完全错失或获得任何东西。这时我开始觉得从 Kubernetes 的角度来看,这种感觉非常熟悉。

resource "aws_ecs_task_definition" "app" {
  family                   = "${var.name}"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "${var.ecs_task_cpu}"
  memory                   = "${var.ecs_task_memory}"
  execution_role_arn       = "${aws_iam_role.ecs_task_execution.arn}"
  task_role_arn            = "${aws_iam_role.ecs_task_execution.arn}"

  container_definitions    = "${module.container_definition_app.json}"

}

现在,为了运行起来我已经写了很多行代码,我阅读了很多 ECS 文档,我所做的就是定义一个任务定义。我还没有让这个东西运行起来。在这一点上,我真的很困惑这个基于 Kubernetes 的平台到底增值了什么,但我继续前行。

服务

服务,一定程度上是将容器如何暴露给外部,另外是如何定义它拥有的副本数量。我的第一个想法是“啊!这就像一个 Kubernetes 服务!”我开始着手映射端口等。这是我第一次在 terraform 上跑:

resource "aws_ecs_service" "app" {
  name                               = "${var.name}"
  cluster                            = "${module.ecs.this_ecs_cluster_id}"
  task_definition                    = "${data.aws_ecs_task_definition.app.family}:${max(aws_ecs_task_definition.app.revision, data.aws_ecs_task_definition.app.revision)}"
  desired_count                      = "${var.ecs_service_desired_count}"
  launch_type                        = "FARGATE"
  deployment_maximum_percent         = "${var.ecs_service_deployment_maximum_percent}"
  deployment_minimum_healthy_percent = "${var.ecs_service_deployment_minimum_healthy_percent}"

  network_configuration {
    subnets          = ["${values(local.private_subnets)}"]
    security_groups  = ["${module.app.this_security_group_id}"]
  }

}

当我必须定义允许访问所需端口的安全组时,我再次感到沮丧,当我这样做了并将其插入到网络配置中后,我就像被扇了一巴掌。

我还需要定义自己的负载均衡器?

什么?

当然不是吗?

负载均衡器从未远离

老实说,我很满意,我甚至不确定为什么。我已经习惯了 Kubernetes 的服务和 Ingress 对象,我一心认为用 Kubernetes 将我的应用程序放到网上是多么容易。当然,我们在 $work 花了几个月的时间建立一个平台,以便更轻松。我是 external-dnscert-manager 的重度用户,它们可以自动填充 Ingress 对象上的 DNS 条目并自动化 TLS 证书,我非常了解进行这些设置所需的工作,但老实说,我认为在 Fargate 上做这件事会更容易。我认识到 Fargate 并没有声称自己是“如何运行应用程序”这件事的全部和最终目的,它只是抽象出节点管理,但我一直被告知这比 Kubernetes 更加容易。我真的很惊讶。定义负载均衡器(即使你不想使用 Ingress 和 Ingress Controller)也是向 Kubernetes 部署服务的重要组成部分,我不得不在这里再次做同样的事情。这一切都让人觉得如此熟悉。

我现在意识到我需要:

  • 一个负载均衡器
  • 一个 TLS 证书
  • 一个 DNS 名字

所以我着手做了这些。我使用了一些流行的 terraform 模块,并做了这个:

# Define a wildcard cert for my app
module "acm" {
  source  = "terraform-aws-modules/acm/aws"
  version = "v1.1.0"

  create_certificate = true

  domain_name = "${var.route53_zone_name}"
  zone_id     = "${data.aws_route53_zone.this.id}"

  subject_alternative_names = [
    "*.${var.route53_zone_name}",
  ]


  tags = "${local.tags}"

}
# Define my loadbalancer
resource "aws_lb" "main" {
  name            = "${var.name}"
  subnets         = [ "${values(local.public_subnets)}" ]
  security_groups = ["${module.alb_https_sg.this_security_group_id}", "${module.alb_http_sg.this_security_group_id}"]
}

resource "aws_lb_target_group" "main" {
  name        = "${var.name}"
  port        = "${var.app_port}"
  protocol    = "HTTP"
  vpc_id      = "${local.vpc_id}"
  target_type = "ip"
  depends_on  = [ "aws_lb.main" ]
}

# Redirect all traffic from the ALB to the target group
resource "aws_lb_listener" "main" {
  load_balancer_arn = "${aws_lb.main.id}"
  port              = "80"
  protocol          = "HTTP"

  default_action {
    target_group_arn = "${aws_lb_target_group.main.id}"
    type             = "forward"
  }
}

resource "aws_lb_listener" "main-tls" {
  load_balancer_arn = "${aws_lb.main.id}"
  port              = "443"
  protocol          = "HTTPS"
  certificate_arn   = "${module.acm.this_acm_certificate_arn}"

  default_action {
    target_group_arn = "${aws_lb_target_group.main.id}"
    type             = "forward"
  }
}

我必须承认,我在这里搞砸了好几次。我不得不在 AWS 控制台中四处翻弄,以弄清楚我做错了什么。这当然不是一个“轻松”的过程,而且我之前已经做过很多次了。老实说,在这一点上,Kubernetes 看起来对我很有启发性,但我意识到这是因为我对它非常熟悉。幸运的是我能够使用托管的 Kubernetes 平台(预装了 external-dns 和 cert-manager),我真的很想知道我漏掉了 Fargate 什么增值的地方。它真的感觉不那么简单。

经过一番折腾,我现在有一个可以工作的 ECS 服务。包括服务在内的最终定义如下所示:

data "aws_ecs_task_definition" "app" {
  task_definition = "${var.name}"
  depends_on      = ["aws_ecs_task_definition.app"]
}

resource "aws_ecs_service" "app" {
  name                               = "${var.name}"
  cluster                            = "${module.ecs.this_ecs_cluster_id}"
  task_definition                    = "${data.aws_ecs_task_definition.app.family}:${max(aws_ecs_task_definition.app.revision, data.aws_ecs_task_definition.app.revision)}"
  desired_count                      = "${var.ecs_service_desired_count}"
  launch_type                        = "FARGATE"
  deployment_maximum_percent         = "${var.ecs_service_deployment_maximum_percent}"
  deployment_minimum_healthy_percent = "${var.ecs_service_deployment_minimum_healthy_percent}"

  network_configuration {
    subnets          = ["${values(local.private_subnets)}"]
    security_groups  = ["${module.app_sg.this_security_group_id}"]
  }

  load_balancer {
    target_group_arn = "${aws_lb_target_group.main.id}"
    container_name   = "app"
    container_port   = "${var.app_port}"
  }

  depends_on = [
    "aws_lb_listener.main",
  ]

}

我觉得我已经接近完成了,但后来我记起了我只完成了最初的“入门”文档中所需的 3 个步骤中的 2 个,我仍然需要定义 ECS 群集。

集群

感谢 定义模块,定义要所有这些运行的集群实际上非常简单。

module "ecs" {
  source  = "terraform-aws-modules/ecs/aws"
  version = "v1.1.0"

  name = "${var.name}"
}

这里让我感到惊讶的是为什么我必须定义一个集群。作为一个相当熟悉 ECS 的人,你会觉得你需要一个集群,但我试图从一个必须经历这个过程的新人的角度来考虑这一点 —— 对我来说,Fargate 标榜自己“ Serverless”而你仍需要定义集群,这似乎很令人惊讶。当然这是一个小细节,但它确实盘旋在我的脑海里。

告诉我你的 Secret

在这个阶段,我很高兴我成功地运行了一些东西。然而,我的原始的成功标准缺少一些东西。如果我们回到任务定义那里,你会记得我的应用程序有一个存放密码的环境变量:

container_environment_variables = [
    {
      name  = "USER"
      value = "${var.user}"
    },
    {
      name  = "PASSWORD"
      value = "${var.password}"
    }
]

如果我在 AWS 控制台中查看我的任务定义,我的密码就在那里,明晃晃的明文。我希望不要这样,所以我开始尝试将其转化为其他东西,类似于 Kubernetes 的Secrets管理

AWS SSM

Fargate / ECS 执行 secret 管理 secret management 部分的方式是使用 AWS SSM(此服务的全名是 AWS 系统管理器参数存储库 Systems Manager Parameter Store,但我不想使用这个名称,因为坦率地说这个名字太愚蠢了)。

AWS 文档很好的涵盖了这个内容,因此我开始将其转换为 terraform。

指定秘密信息

首先,你必须定义一个参数并为其命名。在 terraform 中,它看起来像这样:

resource "aws_ssm_parameter" "app_password" {
  name  = "${var.app_password_param_name}" # The name of the value in AWS SSM
  type  = "SecureString"
  value = "${var.app_password}" # The actual value of the password, like correct-horse-battery-stable
}

显然,这里的关键部分是 “SecureString” 类型。这会使用默认的 AWS KMS 密钥来加密数据,这对我来说并不是很直观。这比 Kubernetes 的 Secret 管理具有巨大优势,默认情况下,这些 Secret 在 etcd 中是不加密的。

然后我为 ECS 指定了另一个本地值映射,并将其作为 Secret 参数传递:

container_secrets = [
    {
      name      = "PASSWORD"
      valueFrom = "${var.app_password_param_name}"
    },
]

module "container_definition_app" {
  source  = "cloudposse/ecs-container-definition/aws"
  version = "v0.7.0"

  container_name  = "${var.name}"
  container_image = "${var.image}"

  container_cpu                = "${var.ecs_task_cpu}"
  container_memory             = "${var.ecs_task_memory}"
  container_memory_reservation = "${var.container_memory_reservation}"

  port_mappings = [
    {
      containerPort = "${var.app_port}"
      hostPort      = "${var.app_port}"
      protocol      = "tcp"
    },
  ]

  environment = "${local.container_environment_variables}"
  secrets     = "${local.container_secrets}"
出了个问题

此刻,我重新部署了我的任务定义,并且非常困惑。为什么任务没有正确拉起?当新的任务定义(版本 8)可用时,我一直在控制台中看到正在运行的应用程序仍在使用先前的任务定义(版本 7)。解决这件事花费的时间比我预期的要长,但是在控制台的事件屏幕上,我注意到了 IAM 错误。我错过了一个步骤,容器无法从 AWS SSM 中读取 Secret 信息,因为它没有正确的 IAM 权限。这是我第一次真正对整个这件事情感到沮丧。从用户体验的角度来看,这里的反馈非常糟糕。如果我没有发觉的话,我会认为一切都很好,因为仍然有一个任务正在运行,我的应用程序仍然可以通过正确的 URL 访问 —— 只不过是旧的配置而已。

在 Kubernetes 里,我会清楚地看到 pod 定义中的错误。Fargate 可以确保我的应用不会停止,这绝对是太棒了,但作为一名运维,我需要一些关于发生了什么的实际反馈。这真的不够好。我真的希望 Fargate 团队的人能够读到这篇文章,改善这种体验。

就这样了

到这里就结束了,我的应用程序正在运行,也符合我的所有标准。我确实意识到我做了一些改进,其中包括:

  • 定义一个 cloudwatch 日志组,这样我就可以正确地写日志了
  • 添加了一个 route53 托管区域,使整个事情从 DNS 角度更容易自动化
  • 修复并重新调整了 IAM 权限,这里太宽泛了

但老实说,现在我想反思一下这段经历。我写了一个关于我的经历的 推特会话,然后花了其余时间思考我在这里的真实感受。

代价

经过一夜的反思,我意识到无论你是使用 Fargate 还是 Kubernetes,这个过程都大致相同。最让我感到惊讶的是,尽管我经常听说 Fargate “更容易”,但我真的没有看到任何超过 Kubernetes 平台的好处。现在,如果你正在构建 Kubernetes 集群,我绝对可以看到这里的价值 —— 管理节点和控制面板只是不必要的开销,问题是 —— 基于 Kubernetes 的平台的大多数消费者都没有这样做。如果你很幸运能够使用 GKE,你几乎不需要考虑集群的管理,你可以使用单个 gcloud 命令来运行集群。我经常使用 Digital Ocean 的 Kubernetes 托管服务,我可以肯定地说它就像操作 Fargate 集群一样简单,实际上在某种程度上它更容易。

必须定义一些基础设施来运行你的容器就是此时的代价。谷歌本周可能刚刚使用他们的 Google Cloud Run 产品改变了游戏规则,但他们在这一领域的领先优势远远领先于其他所有人。

从这整个经历中,我可以肯定的说:大规模运行容器仍然很难。它需要思考,需要领域知识,需要运维和开发人员之间的协作。它还需要一个基础来构建 —— 任何基于 AWS 的操作都需要事先定义和运行一些基础架构。我对一些公司似乎渴望的 “NoOps” 概念非常感兴趣。我想如果你正在运行一个无状态应用程序,你可以把它全部放在一个 lambda 函数和一个 API 网关中,这可能不错,但我们是否真的适合在任何一种企业环境中这样做?我真的不这么认为。

公平比较

令我印象深刻的另一个现实是,技术 A 和技术 B 之间的比较通常不太公平,我经常在 AWS 上看到这一点。这种实际情况往往与 Jeff Barr 博客文章截然不同。如果你是一家足够小的公司,你可以使用 AWS 控制台在 AWS 中部署你的应用程序并接受所有默认值,这绝对更容易。但是,我不想使用默认值,因为默认值几乎是不适用于生产环境的。一旦你开始剥离掉云服务商服务的层面,你就会开始意识到最终你仍然是在运行软件 —— 它仍然需要设计良好、部署良好、运行良好。我相信 AWS 和 Kubernetes 以及所有其他云服务商的增值服务使得它更容易运行、设计和操作,但它绝对不是免费的。

Kubernetes 的争议

最后就是:如果你将 Kubernetes 纯粹视为一个容器编排工具,你可能会喜欢 Fargate。然而,随着我对 Kubernetes 越来越熟悉,我开始意识到它作为一种技术的重要性 —— 不仅因为它是一个伟大的容器编排工具,而且因为它的设计模式 —— 它是声明性的、API 驱动的平台。 在整个 Fargate 过程期间发生的一个简单的事情是,如果我删除这里某个东西,Fargate 不一定会为我重新创建它。自动缩放很不错,不需要管理服务器和操作系统的补丁及更新也很棒,但我觉得因为无法使用 Kubernetes 自我修复和 API 驱动模型而失去了很多。当然,Kubernetes 有一个学习曲线,但从这里的体验来看,Fargate 也是如此。

总结

尽管我在这个过程中遭遇了困惑,但我确实很喜欢这种体验。我仍然相信 Fargate 是一项出色的技术,AWS 团队对 ECS/Fargate 所做的工作确实非常出色。然而,我的观点是,这绝对不比 Kubernetes “更容易”,只是……难点不同。

在生产环境中运行容器时出现的问题大致相同。如果你从这篇文章中有所收获,它应该是这样的:不管你选择的哪种方式都有运维开销。不要相信你选择一些东西你的世界就变得更轻松。我个人的意见是:如果你有一个运维团队,而你的公司要为多个应用程序团队部署容器 —— 选择一种技术并围绕它构建流程和工具以使其更容易。

人们说的一点肯定没错,用点技巧可以更容易地使用某种技术。在这个阶段,谈到 Fargate,下面的漫画这总结了我的感受:


via: https://leebriggs.co.uk/blog/2019/04/13/the-fargate-illusion.html

作者:Lee Briggs 选题:lujun9972 译者:Bestony 校对:wxy, 临石(阿里云智能技术专家)

本文由 LCTT 原创编译,Linux中国 荣誉推出

以及,对于 无服务器 Serverless 架构,什么时候该用,什么时候不该用呢?

如果将如今互联网体验中最方便实用的那一部分去掉,那么留下来的基本就是 客户端-服务端 client-server 模式了。这一个模式在互联网建立初期就已经在使用了,直到目前都没有太大的变化,也就是说,这个模式仍然在为我们服务。

那么,当人们谈论 无服务器 Serverless 架构的时候,到底是指什么呢?其实,无服务器架构并不是说不使用服务器了。恰恰相反,客户端-服务端模式仍然在其中发挥着重要的作用。

无服务器架构实际上指的是能够让开发者在不需要关心服务器上架、为操作系统打补丁、创建容器镜像这些工作的情况下,就能够完成编码、部署和创建应用这一整套流程的架构。

无服务器架构的三个重要意义

  1. 一些缺乏开发经验的人员现在要参与到开发工作中来了。无服务器架构能够让他们尽量只学习必要的工作内容,把更多的时间放在更具创造性的开发工作中。
  2. 开发者不再需要重复造轮子。运行和维护服务器、为操作系统打补丁、创建容器等这一系列工作,都可以由更专业的无服务器架构提供商来完成。
  3. 最现实的一点是,如果不使用无服务器架构,那么在服务器管理方面,总需要有一个作最终决策的人。当服务器发生崩溃时,或是需要在服务器上执行某些操作时,总是需要这样一个统领全局的人来作出决策。因此最佳的方案是使用无服务器架构。

什么时候该用或者不该用无服务器架构?

听起来无服务器架构是个好东西。但事实上,无服务器架构并不是万能的,在使用之前还需要考虑以下这些因素:

  1. 成本
  2. 使用范围
  3. 时间
  4. 控制方式

其中值得注意的是控制方式。现在已经有一些项目为开发者提供了操作和控制无服务器架构计算环境的工具了,Apache OpenWhisk 就是其中之一。

为什么要将无服务器架构开源?

关于这方面的更多内容,可以观看无服务器架构方面的专家 Saron Yitbarek 在 Command Line Heroes 节目中的访谈。


via: https://opensource.com/article/18/12/serverless-podcast-command-line-heros

作者:Jen Wike Huger 选题:lujun9972 译者:HankChow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出