部署与容错

部署由 Vert.x 提供支持的 Knative 服务

本操作指南将向您展示如何部署基于 Vert.x 的 Knative 服务。

您将构建什么

  • 您将编写一个服务,该服务接受 Asciidoc 文本,并使用 Asciidoctor 生成 HTML 渲染。

  • 该服务将使用 Kotlin 编写。

  • 将使用 Jib 创建包含该功能的容器镜像。

  • 该服务将使用 Knative/serving 进行部署。

您需要什么

  • 文本编辑器或 IDE

  • Java 11 或更高版本

  • Maven 或 Gradle

  • Docker

  • 一个运行中的 Kubernetes 集群,并安装了 Knative/serving

什么是 Knative 服务,以及 Vert.x 为何是理想之选?

Knative 启动容器镜像(默认为 3 个)来响应请求,并在没有流量的一段时间延迟后缩容到 0。Knative/serving 提供的“函数”只是一个用任何语言编写并打包为容器镜像的 HTTP 服务。

Vert.x 是在 JVM 上编写 Knative 服务的理想选择,因为

  1. Vert.x 应用程序启动速度非常快,因为运行时没有“魔法”发生,

  2. 可以使用 GraalVM 编译进一步减少启动时间和内存占用(超出本操作指南的范围),

  3. Vert.x 应用程序资源效率高,即使在高负载下也能保持响应,

  4. Vert.x 提供了庞大的响应式客户端生态系统,可连接其他中间件(数据库、消息传递等),

  5. 一个 main 方法/函数就足以启动 Vert.x 应用程序!

创建项目

此项目的代码包含功能等效的 Maven 和 Gradle 构建文件。

使用 Gradle

以下是您应该使用的 build.gradle.kts 文件的内容

1 我们需要 Kotlin、vertx-webasciidoctorj
2 Gradle 应用程序插件允许我们使用 run 命令在本地运行应用程序。
3 用于生成镜像的 Jib 配置。

使用 Maven

以下是您应该使用的 pom.xml 文件的内容

1 我们需要 Kotlin、vertx-webasciidoctorj
2 允许使用 mvn exec:java 运行。
3 用于生成镜像的 Jib 配置。

编写服务

该服务暴露一个 HTTP 服务器。Asciidoc 通过 HTTP POST 请求传递给函数。对于每个请求,Asciidoctor 用于执行到 HTML 的转换。

package io.vertx.howtos.knative.serving

import io.vertx.core.Vertx
import io.vertx.ext.web.Router
import io.vertx.ext.web.handler.BodyHandler
import org.asciidoctor.Asciidoctor
import org.asciidoctor.Options
import org.asciidoctor.SafeMode

fun main() {
  val vertx = Vertx.vertx() (1)

  val asciidoctor = Asciidoctor.Factory.create()  (2)
  val options = Options.builder()
    .safe(SafeMode.SAFE)
    .backend("html5")
    .standalone(true)
    .build()

  val router = Router.router(vertx)
  router.route().handler(BodyHandler.create())  (3)

  router.post().handler { ctx ->  (4)
    ctx.response()
      .putHeader("Content-Type", "text/html")
      .end(asciidoctor.convert(ctx.body().asString(), options))
  }

  vertx.createHttpServer()
    .requestHandler(router)
    .listen(8080)
    .await()
}
1 我们创建一个 Vert.x 上下文。
2 我们配置一个 Asciidoctor 渲染器。
3 我们安装一个 HTTP 请求体处理器,这样我们就可以直接处理整个请求体,而不是手动组装缓冲区。
4 对于每个请求,我们从 Asciidoc 渲染 HTML。

我们可以将 Vert.x 代码编写为一个 verticle,但在 main 函数中这样做可以减少样板代码,因为我们无论如何在这里只部署一个 verticle。

在本地运行函数

我们可以轻松测试服务是否正常工作

  1. 从您的 IDE 运行 main 函数,或

  2. 使用 Gradle:./gradlew run (Linux, macOS) 或 gradle run (Windows)。

  3. 使用 Maven:mvn compile exec:java

然后,您可以上传 Asciidoc 文件的内容,例如此仓库根目录下的 README.adoc 文件。使用 HTTPie,您可以运行类似于以下内容的命令:

http POST :8080/ @README.adoc

准备您的集群

本操作指南中的命令假设您已使用 快速入门 和 Minikube 安装了 Knative。

构建您的容器镜像

您 Gradle 或 Maven 构建中的 Jib 插件将自动组装一个容器镜像,其中包含运行应用程序的正确入口点,并暴露端口 8080。然后,该容器镜像必须被推送到您偏好的仓库。

如果您正在使用 Minikube,可以直接构建并标记容器镜像

eval $(minikube docker-env -p knative)
./gradlew jibDockerBuild    # or mvn package jib:dockerBuild

Docker 应该会列出该镜像

docker image ls

您应该看到类似如下内容

REPOSITORY                                    TAG       IMAGE ID
(...)
dev.local/jponge/knative-vertx-asciidoctor    latest    4ca7aafd590c
dev.local/jponge/knative-vertx-asciidoctor    v1        4ca7aafd590c
(...)

为 Knative 描述服务

以下是文件 service.yaml 中用于通过 Knative/serving 暴露我们服务的描述符

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: knative-vertx-asciidoctor
  namespace: default
spec:
  template:
    spec:
      containers:
        - image: dev.local/jponge/knative-vertx-asciidoctor:v1

然后我们可以应用配置并检查服务是否可用

kubectl apply -f service.yaml

您应该看到类似如下内容

service.serving.knative.dev/knative-vertx-asciidoctor created

然后

kubectl get ksvc

您应该看到类似如下内容

NAME                        URL                                                               LATESTCREATED                     LATESTREADY                       READY   REASON
knative-vertx-asciidoctor   http://knative-vertx-asciidoctor.default.10.101.169.49.sslip.io   knative-vertx-asciidoctor-00001   knative-vertx-asciidoctor-00001   True

测试 Knative 暴露的服务

使用 Minikube,向函数发出请求类似于

http POST knative-vertx-asciidoctor.default.10.101.169.49.sslip.io @README.adoc

您应该在响应中看到 HTML。

如果您的系统无法解析 sslip.io 名称,请从 URL 中提取 IP 并尝试类似以下内容:

http POST 10.101.169.49 'Host:knative-vertx-asciidoctor.default.10.101.169.49.sslip.io' @README.adoc

您还应该看到您的服务的 pod

kubectl get pods

您应该看到类似如下内容

NAME                                                          READY   STATUS    RESTARTS   AGE
knative-vertx-asciidoctor-mlhwq-deployment-5cc999bdb7-jx2ff   3/3     Running   0          2m5s

一段时间后,您可以检查 Knative 自动扩缩器是否已移除所有 pod

kubectl get pods

您应该看到类似如下内容

No resources found.

发出一个新请求,然后您会看到新的 pod 已再次创建。

总结

  • 我们使用 Vert.x 和 Kotlin 编写了一个 Knative 服务,将 Asciidoc 文本渲染为 HTML。

  • 我们构建了一个容器镜像。

  • 我们使用 Knative/serving 部署了该服务。