领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多嗨,Spring 粉丝!欢迎来到另一期 Spring 提示!在本期中,我们将探讨我心中(以及我的 @author
标签!)非常重要的一件事——Cloud Foundry Java 客户端自动配置。
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 客户端。该客户端允许您以编程方式(以及响应式方式)与平台通信并指示它执行操作。在本视频中,我们将介绍现在作为 Spring Cloud Cloud Foundry Discovery Client 实现一部分的相对较新的 Cloud Foundry Java 客户端自动配置。我们不会使用 Discovery Client。(那可能要等到另一个视频才能介绍!)
Java 客户端的设置非常简单,因为现在有一个 Spring Boot 自动配置可以完成连接到平台的大部分工作。让我们使用Spring Initializr创建一个新项目。选择Cloud Foundry Discovery Client
和 Lombok
和 Reactive Web
。单击生成
。
为了演示这一点,我们将部署两个示例应用程序,一个使用 JVM,另一个使用 Python。为了简化操作,我们将使用 Spring CLI 创建一个使用 Spring Boot 和 Groovy 的简单 HTTP 应用程序。然后我们将创建一个 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(一个自包含的“胖”.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
来
SummaryApplicationRequest
很酷,对吧?可编程平台在起作用!现在,与编程平台相关的零开销。
注意:我借用了并极大地简化了重新暂存程序的代码,该代码来自 Josh McKenty 和我在 2017 年制作的 Cloud Foundry Livelessons 培训视频。