Java 无服务器函数入门
Quarkus 无服务器 Java
![](/data/attachment/album/202210/06/154731xejvfcai8e0auimh.jpg)



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


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


开发者随后意识到，可以把同样的无服务器特性应用于微服务和 Linux 容器，带来的好处也是一样的。由此进入 1.5 阶段，在这个阶段，一些无服务器容器完全抽象化了 [Kubernetes](https://opensource.com/article/19/6/reasons-kubernetes)，通过 [Knative](https://cloud.google.com/knative/) 或其它位于它之上的抽象层来提供无服务器的体验。


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


![The serverless Java journey](/data/attachment/album/202210/06/154735b3ijlvyoti4saapv.png)


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


开发者也有可能固执地选择 Spring 框架中的 [Spring 云函数](https://spring.io/serverless) 来进行命令式和反应式函数的开发。Spring 也支持将 Java 函数部署到可安装的无服务器平台，比如 [Kubeless](https://kubeless.io/)、[Apache OpenWhisk](https://openwhisk.apache.org/)、[Fission](https://fission.io/) 和 [Project Riff](https://projectriff.io/)。然而，人们担心 Spring 的启动慢、响应时间长以及内存占用大的问题。在诸如 Kubernetes 这种可扩展的容器环境中运行 Java 函数，这些问题可能会更严重。


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


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


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


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


安装一个本地 Kubernetes 集群，开发者有多种选择，包括 [Minikube](https://minikube.sigs.k8s.io/docs/start/) 和 [OKD](https://docs.okd.io/latest/welcome/index.html)。因为使用 OKD 在 Knative 和 DevOps 工具上安装无服务器相关功能较方便，本文使用 OKD 安装集群。这些关于 [OKD 安装](https://docs.okd.io/latest/installing/index.html) 和 [Knative 操作员安装](https://knative.dev/docs/install/knative-with-operators/) 的相关指南中提供了更多的设置资料。


下面的命令创建了一个 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 应用程序运行，需要使用<ruby> 热部署 <rt>  Live Coding </rt></ruby>。这样，当代码修改后，你就不必重新构建、重新部署以及重启运行时。
> 
> 
> 


现在，你可以使用一个 `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 集群上 [创建命名空间](https://docs.okd.io/latest/applications/projects/configuring-project-creation.html)（例如 `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 网页控制台，就能进入 [开发人员透视图中的拓扑视图](https://docs.okd.io/latest/applications/application_life_cycle_management/odc-viewing-application-composition-using-topology-view.html)。你可能会看到你的<ruby> 容器荚 <rt>  Pod </rt></ruby>（无服务器函数）已经缩小为零（白线圈）。


![Topology view](/data/attachment/album/202210/06/154735bjs1llcol5uccjlu.png)


### 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](/data/attachment/album/202210/06/154736cez3z383x33zg3x3.png)


由于 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](https://opensource.com/users/daniel-oh) 选题：[lkxed](https://github.com/lkxed) 译者：[cool-summer-021](https://github.com/cool-summer-021) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
The [serverless Java](https://opensource.com/article/21/5/what-serverless-java) journey started out with functions—small snippets of code running on demand. This phase didn't last long. Although functions based on virtual machine architecture in the 1.0 phase made this paradigm very popular, as the graphic below shows, there were limits around execution time, protocols, and poor local-development experience.

Developers then realized that they could apply the same serverless traits and benefits to microservices and Linux containers. This launched the 1.5 phase, where some serverless containers completely abstracted [Kubernetes](https://opensource.com/article/19/6/reasons-kubernetes), delivering the serverless experience through [ Knative](https://cloud.google.com/knative/) or another abstraction layer that sits on top of it.

In the 2.0 phase, serverless starts to handle more complex orchestration and integration patterns combined with some level of state management. More importantly, developers want to keep using a familiar application runtime, Java, to run a combination of serverless and non-serverless workloads in legacy systems.

![The serverless Java journey The serverless Java journey](https://opensource.com/sites/default/files/uploads/serverless-journey.png)

(Daniel Oh, CC BY-SA 4.0)

Before Java developers can start developing new serverless functions, their first task is to choose a new cloud-native Java framework that allows them to run Java functions quicker with a smaller memory footprint than traditional monolithic applications. This can be applied to various infrastructure environments, from physical servers to virtual machines to containers in multi- and hybrid-cloud environments.


Developers might consider an opinionated Spring framework that uses the `java.util.function`

package in [ Spring Cloud Function](https://spring.io/serverless) to support the development of imperative and reactive functions. Spring also enables developers to deploy Java functions to installable serverless platforms such as [ Kubeless](https://kubeless.io/), [ Apache OpenWhisk](https://openwhisk.apache.org/), [ Fission](https://fission.io/), and [ Project Riff](https://projectriff.io/). However, there are concerns about slow startup and response times and heavy memory-consuming processes with Spring. This problem can be worse when running Java functions on scalable container environments such as Kubernetes.

[Quarkus](https://quarkus.io/) is a new open source cloud-native Java framework that can help solve these problems. It aims to design serverless applications and write cloud-native microservices for running on cloud infrastructures (e.g., Kubernetes).

Quarkus rethinks Java, using a closed-world approach to building and running it. It has turned Java into a runtime that's comparable to Go. Quarkus also includes more than 100 extensions that integrate enterprise capabilities, including database access, serverless integration, messaging, security, observability, and business automation.

Here is a quick example of how developers can scaffold a Java serverless function project with Quarkus.

## 1. Create a Quarkus serverless Maven project

Developers have multiple options to install a local Kubernetes cluster, including [ Minikube](https://minikube.sigs.k8s.io/docs/start/) and [ OKD](https://docs.okd.io/latest/welcome/index.html) (OpenShift Kubernetes Distribution). This tutorial uses an OKD cluster for a developer's local environment because of the easy setup of serverless functionality on Knative and DevOps toolings. These guides for [ OKD installation](https://docs.okd.io/latest/installing/index.html) and [ Knative operator installation](https://knative.dev/docs/install/knative-with-operators/) offer more information about setting them up.

The following command generates a Quarkus project (e.g., `quarkus-serverless-restapi`

) to expose a simple REST API and download a `quarkus-openshift`

extension for Knative service deployment:

```
$ 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. Run serverless functions locally

Run the application using Quarkus development mode to check if the REST API works, then tweak the code a bit:

`$ ./mvnw quarkus:dev`


The output will look like this:

```
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
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]
```



Note: Keep your Quarkus application running to use Live Coding. This allows you to avoid having to rebuild, redeploy the application, and restart the runtime whenever the code changes.

Now you can hit the REST API with a quick `curl`

command. The output should be `Hello RESTEasy`

:

```
$ curl localhost:8080/hello
Hello RESTEasy
```


Tweak the return text in `GreetingResource.java`

:

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


You will see new output when you reinvoke the REST API:

```
$ curl localhost:8080/hello
Quarkus Function on Kubernetes
```


There's not been a big difference between normal microservices and serverless functions. A benefit of Quarkus is that it enables developers to use any microservice to deploy Kubernetes as a serverless function.

## 3. Deploy the functions to a Knative service

If you haven't already, [ create a namespace](https://docs.okd.io/latest/applications/projects/configuring-project-creation.html) (e.g., `quarkus-serverless-restapi`

) on your OKD (Kubernetes) cluster to deploy this Java serverless function.

Quarkus enables developers to generate Knative and Kubernetes resources by adding the following variables in `src/main/resources/application.properties`

:

```
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>
```


Legend:

<1> Define a project name where you deploy a serverless application


<2> The container registry to use

<3> Use self-signed certs in this simple example to trust them

<4> Enable the generation of Knative resources

<5> Instruct the extension to deploy to OpenShift after the container image is built

<6> Set the Docker build strategy

This command builds the application then deploys it directly to the OKD cluster:

`$ ./mvnw clean package -DskipTests`



Note:Make sure to log in to the right project (e.g.,`quarkus-serverless-restapi`

) by using the`oc login`

command ahead of time.

The output should end with `BUILD SUCCESS`

.

Add a Quarkus label to the Knative service with this `oc`

command:

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


Then access the OKD web console to go to the [ Topology view in the Developer perspective](https://docs.okd.io/latest/applications/application_life_cycle_management/odc-viewing-application-composition-using-topology-view.html). You might see that your pod (serverless function) is already scaled down to zero (white-line circle).

![Topology view Topology view](https://opensource.com/sites/default/files/uploads/topologyview.png)

(Daniel Oh, CC BY-SA 4.0)

## 4. Test the functions on Kubernetes

Retrieve a route `URL`

of the serverless function by running the following `oc`

command:

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


Access the route `URL`

with a `curl`

command:

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


In a few seconds, you will get the same result as you got locally:

`Quarkus Function on Kubernetes`


When you return to the Topology view in the OKD cluster, the Knative service scales up automatically.

![Scaling the Knative Function Scaling the Knative Function](https://opensource.com/sites/default/files/uploads/scale-up-knative-function.png)

(Daniel Oh, CC BY-SA 4.0)

This Knative service pod will go down to zero again in 30 seconds because of Knative serving's default setting.

## What's next?

The serverless journey has evolved, starting with functions on virtual machines to serverless containers and integration with enterprise legacy systems. Along this journey, enterprise developers can still use familiar technologies like Java for developing serverless functions by using Quarkus to create a project then build and deploy it to Kubernetes with a Knative service.

The next article in this series will guide you on optimizing Java serverless functions in Kubernetes for faster startup time and small memory footprints at scale.

## 1 Comment