5个月前 (06-04)  Serverless |   抢沙发  79 
文章评分 0 次,平均分 0.0

使用Knative运行Spring Boot项目
在本文中,我将解释什么是Knative以及如何将它与Spring Boot一起使用。尽管Knative是一个serverless无服务器平台,但我们可以在那里运行任何类型的应用程序(不仅仅是函数)。因此,我们将在那里运行一个标准的Spring Boot应用程序,它公开restapi并连接到数据库。

Knative介绍了一种在Kubernetes上管理应用程序的新方法。它扩展了Kubernetes,添加了一些新的关键特性。其中最重要的是“零缩容”。如果Knative检测到某个服务未被使用,它会将正在运行的实例数量缩减为零。因此,它提供了基于并发性或每秒请求数的内置自动缩放功能。我们还可以利用修订跟踪,它负责从应用程序的一个版本切换到另一个版本。有了Knative,你只需要专注于你的核心逻辑。

我上面描述的所有特性都是由名为“Knative Serving”的组件提供的。还有另外两个组件:“Eventing”和“Build”。构建组件已弃用,已被Tekton替换。事件组件需要注意。

源代码

如果你想自己试试,你可以随时看看我的源代码。为此,您需要克隆我的GitHub存储库:https://github.com/piomin/sample-spring-boot-on-kubernetes.git

我在以前的一些关于Spring BootKubernetes的文章中使用了与示例相同的应用程序。我只想强调的是,在Knative上运行它不需要修改源代码中的任何内容。唯一需要的更改将在YAML清单中。

由于Knative提供了内置的自动缩放功能,您可能需要将其与Kubernetes上的水平pod自动缩放器(HPA)进行比较。

在Kubernetes上安装Knative

当然,在开始Spring Boot开发之前,我们需要在Kubernetes上安装Knative。我们可以使用kubectl CLI或操作符来完成。我决定在OpenShift上试试。这显然是最快的方法。我可以使用OpenShift无服务器操作符单击一下。无论您选择哪种类型的安装,进一步的步骤将适用于所有地方。

使用Knative CLI

此步骤是可选的。您可以使用CLI在Knative上部署和管理应用程序。将CLI下载到站点https://knative.dev/docs/install/install-kn/. 然后可以使用Docker映像部署应用程序。

$ kn service create sample-spring-boot-on-kubernetes \
   --image piomin/sample-spring-boot-on-kubernetes:latest

我们还可以使用以下命令验证正在运行的服务的列表。

$ kn service list

对于更高级的部署,更适合使用YAML清单。我们将从skafold和Jib的源代码构建开始构建。首先,让我们简单地看一下Spring Boot应用程序。

Knative的Spring Boot应用

如前所述,我们将创建一个典型的基于Spring-Boot-REST的应用程序,该应用程序连接到Mongo数据库。数据库部署在Kubernetes上。我们的模型类使用MongoDB中的person集合。我们来看看。

@Document(collection = "person")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Person {

   @Id
   private String id;
   private String firstName;
   private String lastName;
   private int age;
   private Gender gender;
}

我们使用Spring Data MongoDB将我们的应用程序与数据库集成。为了简化这个集成,我们利用了它的“存储库”特性。

public interface PersonRepository extends CrudRepository<Person, String> {
   Set<Person> findByFirstNameAndLastName(String firstName, String lastName);
   Set<Person> findByAge(int age);
   Set<Person> findByAgeGreaterThan(int age);
}

我们的应用程序公开了几个用于添加、搜索和更新数据的REST端点。下面是控制器类的实现。

@RestController
@RequestMapping("/persons")
public class PersonController {

   private PersonRepository repository;
   private PersonService service;

   PersonController(PersonRepository repository, PersonService service) {
      this.repository = repository;
      this.service = service;
   }

   @PostMapping
   public Person add(@RequestBody Person person) {
      return repository.save(person);
   }

   @PutMapping
   public Person update(@RequestBody Person person) {
      return repository.save(person);
   }

   @DeleteMapping("/{id}")
   public void delete(@PathVariable("id") String id) {
      repository.deleteById(id);
   }

   @GetMapping
   public Iterable<Person> findAll() {
      return repository.findAll();
   }

   @GetMapping("/{id}")
   public Optional<Person> findById(@PathVariable("id") String id) {
      return repository.findById(id);
   }

   @GetMapping("/first-name/{firstName}/last-name/{lastName}")
   public Set<Person> findByFirstNameAndLastName(@PathVariable("firstName") String firstName,
			@PathVariable("lastName") String lastName) {
      return repository.findByFirstNameAndLastName(firstName, lastName);
   }

   @GetMapping("/age-greater-than/{age}")
   public Set<Person> findByAgeGreaterThan(@PathVariable("age") int age) {
      return repository.findByAgeGreaterThan(age);
   }

   @GetMapping("/age/{age}")
   public Set<Person> findByAge(@PathVariable("age") int age) {
      return repository.findByAge(age);
   }

}

我们使用环境变量注入数据库连接设置和凭据。我们的应用程序公开了用于活动性和就绪性健康检查的端点。就绪端点验证与Mongo数据库的连接。当然,我们使用的内置功能,从弹簧启动执行器。

spring:
  application:
    name: sample-spring-boot-on-kubernetes
  data:
    mongodb:
      uri: mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@mongodb/${MONGO_DATABASE}

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint.health:
      show-details: always
      group:
        readiness:
          include: mongo
      probes:
        enabled: true

在YAML中定义Knative服务

首先,我们需要用一个Knative服务定义定义一个YAML清单。它设置了一个自动缩放策略,使用可动吊舱自动缩放(千帕)。为了做到这一点,我们必须添加注释autoscaling.knative.dev/target,其中包含每个应用程序实例可以同时处理的请求数。默认情况下,它是100。我们将该限制减少到20个请求。当然,我们需要为容器设置活动性和就绪性探测器。此外,我们还参考SecretConfigMap来注入MongoDB设置。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: sample-spring-boot-on-kubernetes
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/target: "20"
    spec:
      containers:
        - image: piomin/sample-spring-boot-on-kubernetes
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
          env:
            - name: MONGO_DATABASE
              valueFrom:
                secretKeyRef:
                  name: mongodb
                  key: database-name
            - name: MONGO_USERNAME
              valueFrom:
                secretKeyRef:
                  name: mongodb
                  key: database-user
            - name: MONGO_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mongodb
                  key: database-password

配置Skaffold和Jib进行Knative部署

我们将使用skafold在Knative上自动部署我们的应用程序。Skaffold是一个命令行工具,允许使用单个命令在Kubernetes上运行应用程序。您可以在Kubernetes上的localjava开发一文中了解更多。它可以很容易地与jibmaven插件集成。我们只需要在Skaffold配置的build部分将jib设置为默认选项。我们还可以定义在部署阶段执行的YAML脚本的列表。skaffold.yaml文件应该放在项目根目录中。这是Skaffold当前的配置。如您所见,它使用Knative服务定义运行脚本。

apiVersion: skaffold/v2beta5
kind: Config
metadata:
  name: sample-spring-boot-on-kubernetes
build:
  artifacts:
    - image: piomin/sample-spring-boot-on-kubernetes
      jib:
        args:
          - -Pjib
  tagPolicy:
    gitCommit: {}
deploy:
  kubectl:
    manifests:
      - k8s/mongodb-deployment.yaml
      - k8s/knative-service.yaml

Skafold在构建期间激活起重臂配置文件。在这个概要文件中,我们将放置一个jib-maven-plugin。Jib对于在无码头模式下构建图像非常有用。

<profile>
   <id>jib</id>
   <activation>
      <activeByDefault>false</activeByDefault>
   </activation>
   <build>
      <plugins>
         <plugin>
            <groupId>com.google.cloud.tools</groupId>
            <artifactId>jib-maven-plugin</artifactId>
            <version>2.8.0</version>
         </plugin>
      </plugins>
   </build>
</profile>

最后,我们需要做的就是运行以下命令。它构建我们的应用程序,创建并推送Docker映像,并使用Knative-service.yaml在Knative上运行它。

$ skaffold run

验证Knative上的Spring Boot部署

现在,我们可以验证我们在Knative上的部署。为此,让我们执行命令kn service list,如下所示。我们在kubernetes上有一个名为sample-spring-boot-on-kubernetes的Knative服务。

使用Knative运行Spring Boot项目

然后,假设我们部署了应用程序的三个版本(修订版)。为此,我们只需在源代码中提供一些更改,并使用skaffoldrun重新部署服务。它对我们的服务进行了新的修改。但是,整个流量被转发到最新版本(后缀为-vlskg)。

使用Knative运行Spring Boot项目

有了Knative,我们可以很容易地在单个服务的多个版本之间分割流量。为此,我们需要在Knative服务YAML配置中添加一个traffic部分。我们定义了一个单一版本的总流量的百分比,如下所示。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: sample-spring-boot-on-kubernetes
  spec:
    template:
      ...
    traffic:
      - latestRevision: true
        percent: 60
        revisionName: sample-spring-boot-on-kubernetes-vlskg
      - latestRevision: false
        percent: 20
        revisionName: sample-spring-boot-on-kubernetes-t9zrd
      - latestRevision: false
        percent: 20
        revisionName: sample-spring-boot-on-kubernetes-9xhbw

让我们看看当前体系结构的图形表示。60%的流量转发到最新版本,而之前的两个版本接收20%的流量。

使用Knative运行Spring Boot项目

自动扩缩容和缩放到零

默认情况下,Knative支持自动缩放。我们可以在两种类型的目标之间进行选择:并发和每秒请求数(RPS)。默认目标是并发。您可能还记得,我已经用autoscaling.knative.dev/target注释将这个默认值重写为20。所以,我们现在的目标是验证自动缩放。为此,我们需要同时向应用程序发送许多请求。当然,传入的流量分布在Knative服务的三个不同版本上。

幸运的是,我们可以很容易地用围攻工具模拟一个大流量。我们将调用返回所有可用人员的GET/persons端点。我们正在发送150个并发请求,命令如下所示。

$ siege http://sample-spring-boot-on-kubernetes-pminkows-serverless.apps.cluster-7260.7260.sandbox1734.opentlc.com/persons \
   -i -v -r 1000  -c 150 --no-parser

在引擎盖下,Knative仍然会创建一个部署,并缩小或扩大跑步舱的数量。因此,如果一个服务有三个修订版,则会创建三个不同的部署。最后,我有10个最新部署的运行pod,它接收60%的流量。以前的版本还有3个和2个跑步舱。

使用Knative运行Spring Boot项目

如果没有车辆进入服务区,会发生什么情况?Knative将把所有部署的运行吊舱数量缩减到零。

使用Knative运行Spring Boot项目

结论

在本文中,您学习了如何使用Skaffold和Jib将Spring Boot应用程序部署为Knative服务。我用示例说明了如何创建服务的新修订版,以及如何在这些修订版之间分发流量。我们还使用基于并发请求的自动缩放来测试场景,并在没有传入流量的情况下将其缩放为零。

原文地址:https://piotrminkowski.com/2021/03/01/spring-boot-on-knative/

 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1984.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册