先行一步
VMware 提供培训和认证,助你加速前进。
了解更多Spring 粉丝们大家好!在这个由 8 部分组成的简短系列中,我们将探讨 Spring Cloud 对 Google Cloud Platform 的集成,称为 Spring Cloud GCP。Spring Cloud GCP 代表了 Google 和 Pivotal 之间的共同努力,旨在为使用 Google Cloud Platform 的 Spring Cloud 开发者提供一流的体验。Pivotal Cloud Foundry 用户将享受到更易于集成的 GCP 服务代理。我撰写这些部分时,得到了 Google Cloud 开发者布道师、我的朋友 Ray Tsang 的帮助。你还可以在我们 Google Next 2018 的会议上观看 Spring Cloud GCP 的演示,会议标题是 Bootiful Google Cloud Platform。谢谢朋友!一如既往,如果你有任何反馈,我很乐意听取。
本系列共有八篇文章。它们如下:
到目前为止,我们已经看过了一些简单的例子,除了最基本的配置之外。凡有配置之处,我们都在 application.properties
中指定了。这种方法可行,但存在局限性。那么,集中化(使一个配置值可供多个其他客户端访问)、安全性(安全存储秘密)、实时重新配置以及审计和日志记录怎么办呢?还有许多其他解决方案可以解决这些用例中的一部分或全部,包括 Apache Zookeeper、Hashicorp Consul、Hashicorp Vault(尤其用于秘密管理)以及——当然——Spring Cloud Config Server。这些都是不错的选择,但你最好有扩展和保护这些基础设施的方案。GCP 提供了一个替代方案,Google Cloud RuntimeConfig,借助 Spring 抽象的强大力量,你可以无需更改现有代码即可使用它。
让我们来看看如何建立一个配置值,然后在我们的应用程序中引用该值。我们还将探讨如何在不重启应用程序的情况下实时更新配置。
首先,我们需要启用此 API。
gcloud services enable runtimeconfig.googleapis.com
让我们仔细思考一下我们希望如何使用此配置。当在本地机器上运行应用程序时,我们可能有一些有意义的配置值。这些值可以来源于内置的 application.properties
或 application.yaml
文件。这些是适用于应用程序的默认值。还有一些值只在生产环境中可见——例如定位符、凭据等——它们是生产环境所独有的。例如,当在 cloud
配置文件下运行时,这些值可能会被看到。当在 cloud
配置文件下运行时,我们将从 Google Cloud Runtime Config 获取这些值。通过这种方式,我们可以选择性地覆盖重要值。
我们必须首先创建一个运行时配置,然后向该配置添加一个变量值。
gcloud beta runtime-config configs create reservations_cloud
然后,在刚刚创建的运行时配置中注册一个变量 (greeting
) 及其值 (Hello GCP
)。
gcloud beta runtime-config configs variables set greeting "Hello GCP" --config-name reservations_cloud
我们可以像这样枚举给定配置集的所有配置
gcloud beta runtime-config configs variables list --config-name=reservations_cloud
Spring Cloud GCP 需要在大多数 Spring 应用程序运行之前工作,因为它是一个属性源,会为其他配置提供值。因此,它进行工作所需的任何配置必须比 application.properties
等常规文件中的配置更早可访问。在 Spring Cloud 中,约定此类配置位于 bootstrap.properties
文件中。当在本地机器上运行且没有激活任何特定的 Spring profile 时,让我们禁用 Spring Cloud GCP Runtime Config。
src/main/resources/bootstrap.properties 文件。
spring.cloud.gcp.config.enabled=false
spring.cloud.gcp.config.credentials.location=${spring.cloud.gcp.credentials.location}
当我们在生产环境中运行时,例如在 Cloud Foundry 中,我们会想要激活 cloud
profile,此时 Spring Cloud GCP Runtime Config 客户端将启动并从 GCP 获取配置。Spring Boot 在加载任何 profile 特定配置的同时加载默认配置方面非常智能。你只需将配置文件名后缀为 -${YOUR_PROFILE}
即可:例如:对于 Spring profile foo
和 bar
,分别为 application-foo.properties
或 bootstrap-bar.yml
。让我们在 cloud
profile 激活时配置 Spring Cloud GCP。
src/main/resources/bootstrap-cloud.properties 文件。
spring.cloud.gcp.config.enabled=true
spring.cloud.gcp.config.name=reservations
spring.cloud.gcp.config.profile=cloud
注意
${spring.cloud.gcp.config.name}_${spring.cloud.gcp.config.profile}
的组合形成了reservations_cloud
,这是我们刚刚创建的运行时配置的名称。
我们将在 src/main/resources/application.properties
中配置一些总体属性,这些属性将在没有覆盖的情况下作为默认值。
src/main/resources/application.properties 文件。
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=*
greeting = Hello ${user.name} (running on ${os.name} ${os.version})!
对于这个 DEMO,我们希望暴露所有的 Actuator 端点,以便能够查询它们。在任何其他情况下:请配置安全性!
我们希望包含所有 Actuator 端点
现在让我们转向 Java 代码。你需要将以下依赖项添加到你的构建中:org.springframework.boot
: spring-boot-starter-web
, org.springframework.boot
: spring-boot-starter-actuator
, org.springframework.cloud
: spring-cloud-gcp-starter-config
。我们添加 Spring Cloud GCP 依赖项以获取正确的运行时配置支持配置。我们添加 Spring Boot Actuator,以便访问一些操作端点,/actuator/env
和 /actuator/refresh
。
让我们看看代码!
package com.example.gcp.runtimeconfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class RuntimeConfigApplication {
@RefreshScope
@RestController
public static class GreetingsRestController {
private final String greetings;
GreetingsRestController(@Value("${greeting}") String greetings) {
this.greetings = greetings;
}
@GetMapping("/greeting")
String greetings() {
return this.greetings;
}
}
public static void main(String[] args) {
SpringApplication.run(RuntimeConfigApplication.class, args);
}
}
此注解支持修改和刷新此 bean 的配置。我们可以触发一个刷新事件,并在 bean 中观察到更新的配置
我们正在从属性文件或 GCP Runtime Config 中注入键。就代码而言,它们完全相同。
在没有激活任何 profile 的情况下运行此程序,并在访问 http://localhost:8080/greeting
端点时,你应该会看到类似 Hello jlong!
的输出。访问这个环境 Actuator 端点 (http://localhost:8080/actuator/env
),你会发现没有提及我们的 GCP Runtime Config 配置。现在,在激活 cloud
profile 的情况下运行程序,再次访问 /greeting
端点,你会在控制台输出中看到类似 Hello GCP
的内容。访问 /actuator/env
端点,你会看到一个包含我们的 Runtime Config 值的 bootstrapProperties:spring-cloud-gcp
条目。
提示
你可以在运行应用程序时通过为 profile
foo
和bar
指定-Dspring.profiles.active=foo,bar
来更改活动的 profile。
到目前为止我喜欢我们的应用程序,但问候语听起来太生硬了!我很想改变它,但又不想停止并重新启动每个应用程序实例。在这里,我们可以利用 /actuator/refresh
端点在更新 Runtime Config 配置中的值后刷新我们节点的配置。让我们把值改成不那么正式的内容,比如 Hi, GCP
。
gcloud beta runtime-config configs variables set greeting "Hi, GCP" --config-name reservations_cloud
配置已经在 GCP Runtime Config 中改变了,但这个改变默认情况下对我们的应用程序是不可见的。我们需要强制 Spring Boot 刷新其本地配置,从 Runtime Config 服务中获取配置。向 /actuator/refresh
端点发出一个(空的)HTTP POST 命令,然后访问 /greeting
端点以查看更新后的值。
curl http://localhost:8080/greeting
> Hello GCP
gcloud beta runtime-config configs variables set greeting "Hi GCP" --config-name reservations_cloud
curl -H"content-type: application/json" -d{} http://localhost:8080/actuator/refresh
curl http://localhost:8080/greeting
> Hi GCP
检查旧值
改变值,然后强制客户端刷新其配置。你将能够确认更新。