Spring 提示:使用 Spring Cloud Cloud Foundry Java 客户端自动配置操作平台

工程 | Josh Long | 2020年4月1日 | ...

嗨,Spring 粉丝!欢迎来到另一期 Spring 提示!在本期中,我们将探讨我心中(以及我的 @author 标签!)非常重要的一件事——Cloud Foundry Java 客户端自动配置。

什么是 Cloud Foundry?

Cloud Foundry 是一个开源的 PaaS。它具有很强的灵活性。说实话,我非常喜欢它。它很简单。我喜欢像它这样的东西,它可以让我灵活地操作,而无需在 YAML 神灵的祭坛上做出太多牺牲。它是一个有观点的平台即服务。您将应用程序提供给平台,它就会部署它们。您上传一个 Spring Boot 应用程序,它会识别出该应用程序是一个独立的、自包含的、所谓的“胖”.jar 文件,然后它会下载所需的 JDK,配置必要的内存量,然后创建一个包含您的应用程序、JDK、正确配置的文件系统,然后将其全部转换为容器。

好吧,准确地说,构建包是接收上传的工件并为其派生运行时和环境以运行应用程序的组件。然后,构建包会在平台的各种经过认可的操作系统版本之上添加层。结果是一致性。您通过一致性获得速度。通过了解每个应用程序的外观都基本上相同,您可以获得速度。平台使用类似的配置运行所有这些应用程序,并允许对 RAM、硬盘空间等内容进行一些更改。

这种方法的另一个好处是,平台负责构建容器。整个容器创建生命周期都通过平台进行路由。如果需要,平台可以重新创建环境,例如当基础平台存在安全修复程序时。平台可以透明地重建这些内容以利用新的平台修复程序。您也可以这样做。

在 Cloud Foundry 中,重新暂存应用程序的行为会强制其重建该环境。平台也可以自动为您执行此操作。如果需要,您可以进行滚动重新暂存。您可能执行此操作是因为您希望指定一些新的环境变量。需要将新的消息队列或数据库绑定到应用程序?重新暂存它。如果要升级 JDK 或构建包描述的其他任何内容,也可以这样做。Java 14 发布了吗?太好了,让我们使用它。

Cloud Foundry 使这种工作变得轻松,因为它全部可以通过 HTTP REST API 进行控制。您可以询问平台,您有哪些应用程序正在使用——比如说——基于 Python 的构建包?哪个正在使用 Java?然后您可以告诉它只暂存那些应用程序。

Cloud Foundry Java 客户端

之前的视频中,我们介绍了 Cloud Foundry Java 客户端。该客户端允许您以编程方式(以及响应式方式)与平台通信并指示它执行操作。在本视频中,我们将介绍现在作为 Spring Cloud Cloud Foundry Discovery Client 实现一部分的相对较新的 Cloud Foundry Java 客户端自动配置。我们不会使用 Discovery Client。(那可能要等到另一个视频才能介绍!)

Java 客户端的设置非常简单,因为现在有一个 Spring Boot 自动配置可以完成连接到平台的大部分工作。让我们使用Spring Initializr创建一个新项目。选择Cloud Foundry Discovery ClientLombokReactive Web。单击生成

我们的示例应用程序

为了演示这一点,我们将部署两个示例应用程序,一个使用 JVM,另一个使用 Python。为了简化操作,我们将使用 Spring CLI 创建一个使用 Spring Boot 和 Groovy 的简单 HTTP 应用程序。然后我们将创建一个 Python 应用程序。

要部署这些应用程序,您需要在 Cloud Foundry 实例上拥有一个帐户。我正在使用Pivotal Web Services。注册非常便宜。如果您已经有实例,请登录。

Python 应用程序

这是Python 应用程序

Python 应用程序(application.py)是一个类似的简单 HTTP 应用程序,使用 Python 的 Flask 框架。

#!/usr/bin/env python
from flask import Flask
import os

app = Flask(__name__)
cf_port = os.getenv("PORT")
if cf_port is None:
    cf_port = '5000'

@app.route('/')
def hello():
    return {'message': 'Hello, world'}

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=int(cf_port), debug=True)

HerokuCloud Foundry 使用Procfile 文件告诉平台 Python 应用程序应该是一个 Web 应用程序。它向平台描述了如何运行程序。

web: Python application.py

当平台看到传入的应用程序时,它必须下载运行应用程序的所有工件。您可以使用Pipfile 文件执行此操作,该文件有点类似于 Maven 的熟悉的pom.xml

[[source]]
name = "pypi"
url = "https://pypi.ac.cn/simple"
verify_ssl = true

[dev-packages]

[packages]
flask = "*"

[requires]
python_version = "3.7"

这是我用来部署应用程序的部署脚本deploy.sh

#!/bin/bash

APP_NAME=sample-python-app-${RANDOM}
cf push -p . ${APP_NAME}

Java 应用程序

这是Java 应用程序

以下是基于 Spring Boot CLI 的工作应用程序——全部内容。

@RestController 
class GreetingsRestController {

    @GetMapping("/hello")
    String get (){
        return "Hello, world"
    }
}

为了部署它,我编写了一个名为deploy.sh的小脚本,其中包含以下咒语。该脚本有两行:一行将.groovy 脚本转换为一个可工作的 Spring Boot(一个自包含的“胖”.jar 文件,其中包含所有依赖项)应用程序,另一行用于部署它。

#!/bin/bash 
APP_NAME=hello-world-${RANDOM}
JAR_NAME=app.jar
spring jar  ${JAR_NAME} hello.groovy 
cf push -p ${JAR_NAME} APP_NAME

使用 Cloud Foundry 自动配置进行重新暂存

好吧,我想演示一下能够在属性文件中插入一些字符串然后——瞧!——您现在就可以使用出色的 Cloud Foundry Java 客户端操作平台是多么酷。但是没什么可看的!您只需将 Spring Boot 依赖项添加到类路径并插入一些属性即可。因此,我将向您展示构建选择性重新暂存的代码和配置。我已经向您展示了无数个关于构建响应式应用程序的不同视频;我不会回顾这些基础知识。让我们只看看一些代码。

首先,这是配置属性。我将让您自己指定值。在上面的视频中,我将它们定义为环境变量(export SPRING_CLOUD_CLOUNDFOUNDRY_USERNAME=...)。

spring.cloud.cloudfoundry.space=joshlong
spring.cloud.cloudfoundry.org=my-org
spring.cloud.cloudfoundry.password=wouldnt-u-like-to-know
spring.cloud.cloudfoundry.username=my-user-email
spring.cloud.cloudfoundry.url=api.run.pivotal.io

现在是实际的 Java 代码。

package com.example.cfac;

import lombok.SneakyThrows;
import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j2;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.client.v2.applications.SummaryApplicationRequest;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.applications.RestageApplicationRequest;
import org.cloudfoundry.operations.applications.StopApplicationRequest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@SpringBootApplication
public class CfacApplication {

    @SneakyThrows
    public static void main(String[] args) {
        SpringApplication.run(CfacApplication.class, args);
        System.in.read();
    }
}

@Component
@Log4j2
class Restager {

    private final String buildpack = "python";

    private boolean isValidBuildpack(String one, String two) {
        return (StringUtils.hasText(one) ? one : StringUtils.hasText(two) ? two : "").contains(this.buildpack);
    }

    Restager(CloudFoundryOperations ops, CloudFoundryClient client) {
        ops
            .applications()
            .list()
            .filter(as -> as.getRunningInstances() > 0)
            .flatMap(as -> client.applicationsV2().summary(SummaryApplicationRequest.builder().applicationId(as.getId()).build()))
            .filter(as -> isValidBuildpack(as.getBuildpack(), as.getDetectedBuildpack()))
            .doOnNext(as -> log.info("restaging " + as.getName() + '.'))
            .flatMap(as -> ops.applications().restage(RestageApplicationRequest.builder().name(as.getName()).build()))
            .subscribe();
    }
}

该应用程序相对简单。它使用CloudFoundryOperations

  • 加载所有应用程序
  • 过滤当前正在运行的应用程序
  • 为正在运行的应用程序加载SummaryApplicationRequest
  • 确定应用程序是否使用我们正在查找的构建包(在本例中为 Python 构建包)
  • 确定它们的构建包
  • 然后重新暂存它们。

很酷,对吧?可编程平台在起作用!现在,与编程平台相关的开销。

注意:我借用了并极大地简化了重新暂存程序的代码,该代码来自 Josh McKenty 和我在 2017 年制作的 Cloud Foundry Livelessons 培训视频

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部