快人一步
VMware 提供培训和认证,助您加速进步。
了解更多嗨,Spring 粉丝们!欢迎来到新一期的 Spring Tip!在本期中,我们将介绍一个我非常喜欢(并且我的 `@author` 标签也与此相关!)的话题——Cloud Foundry Java 客户端自动配置。
Cloud Foundry 是一个开源的 PaaS。它非常灵活。老实说,我非常喜欢它。它很简单。我喜欢它这种提供灵活性的方式,而无需在 YAML 之神面前做出太多牺牲。它是一个有主见的平台即服务。您将一个应用程序交给平台,它就会进行部署。您上传一个 spring boot 应用程序,它就会识别出该应用程序是一个独立的、自包含的、所谓的“fat” `.jar`,然后下载所需的 JDK,配置必要的内存量,接着创建一个文件系统,其中包含您的应用程序、JDK 和正确的配置,然后将这一切都转化为一个容器。
嗯,确切地说,构建包(buildpacks)是将上传的工件转换为运行应用程序所需的运行时和环境的东西。构建包随后会叠加到平台各种经过认证的操作系统版本之上。这样带来了稳定性。通过稳定性获得速度。通过知道每个应用程序看起来“基本上”都一样来获得速度。平台使用类似的配置来运行它们,允许一些变化,例如内存、硬盘空间等。
这种方法的另一个好处是平台负责构建容器。整个容器创建生命周期都通过平台路由。如果需要,例如平台基础有安全补丁时,平台可以再次创建环境。平台可以透明地重建这些东西,以利用新的平台补丁。您也可以这样做。
在 Cloud Foundry 中,重置应用程序(restaging)的动作会强制它重建该环境。平台也可以自动为您完成此操作。如果需要,您可以进行滚动重置。您可能这样做是因为想要指定一些新的环境变量。应用程序是否有新的消息队列或数据库需要绑定?重置它。如果您想升级 JDK 或构建包描述的其他任何东西,也可以这样做。Java 14 发布了?太棒了,让我们开始使用它。
Cloud Foundry 使此类工作变得容易,因为它都可以通过 HTTP REST API 进行控制。您可以询问平台,有哪些应用程序正在使用(例如)基于 Python 的构建包?哪些正在使用 Java?然后您可以告诉它只部署这些应用程序。
在之前的视频中,我们介绍了 Cloud Foundry Java 客户端。该客户端允许您通过编程方式(以及响应式方式)与平台通信并指示它执行操作。在此视频中,我们将介绍相对较新的 Cloud Foundry Java 客户端自动配置,它现在是 Spring Cloud Cloud Foundry Discovery Client 实现的一部分。我们**不会**使用 Discovery Client。(这可能需要等待另一个视频!)
由于现在有了 Spring Boot 自动配置来完成连接平台的绝大部分工作,Java 客户端的设置变得非常简单。让我们在 Spring Initalizr 上构建一个新项目。选择 `Cloud Foundry Discovery Client`、`Lombok` 和 `Reactive Web`。点击 `Generate`。
为了演示这一点,我们将部署两个示例应用程序,一个使用 JVM,另一个使用 Python。为了保持简单,我们将使用 Spring CLI 创建一个简单的 HTTP 应用程序,使用 Spring Boot 和 Groovy。然后我们将创建一个 Python 应用程序。
要部署这些应用程序,您需要在 Cloud Foundry 实例上拥有一个帐户。我使用的是 Pivotal Web Services。注册费用很低。如果您已经有一个实例,请登录。
这是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)
Heroku 和 Cloud 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 应用程序。
以下是一个基于 Spring Boot CLI 的工作应用程序——全部在此。
@RestController
class GreetingsRestController {
@GetMapping("/hello")
String get (){
return "Hello, world"
}
}
为了部署它,我写了一个小小的 `deploy.sh`,其中包含以下咒语。该脚本有两行:一行用于将 `.groovy` 脚本转换为一个工作的 Spring Boot 应用程序(一个自包含的“fat” `.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 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` 来
很酷吧?可编程平台正在发挥作用!现在,编程平台没有任何开销。
注意:我借鉴并极大地简化了重置器代码(来自 Cloud Foundry Livelessons 培训视频),该视频是我和 Josh McKenty 在 2017 年制作的。