1. 概述
本文将带你快速掌握 Spring Cloud Open Service Broker 项目,学习如何实现 Open Service Broker API 规范。
我们会先了解 Open Service Broker API 的核心设计思想,然后使用 Spring Cloud Open Service Broker 快速搭建一个符合规范的服务代理应用。最后,还会探讨如何为这些关键接口加上安全防护。
✅ 适合场景:你想把自研系统(如邮件服务、消息中间件、数据库代理)无缝集成到 Cloud Foundry、Kubernetes 等云原生平台时,这个框架就是你的“桥梁”。
2. Open Service Broker API 简介
Open Service Broker API 的目标很明确:让云原生平台(如 Cloud Foundry、Kubernetes)能统一方式对接后端服务。它本质上定义了一套标准的 REST 接口,平台通过这些接口完成服务的“上架”、创建、绑定和销毁。
具体来说,一个服务代理(Service Broker)可以在云平台中实现以下能力:
- ✅ 提供服务目录(Catalog):告诉平台“我能提供哪些服务”
- ✅ 创建服务实例(Provision):为应用分配一个独立的服务资源(如数据库实例)
- ✅ 绑定服务(Bind):生成访问凭据(如用户名、密码、连接地址),供应用使用
- ✅ 销毁服务实例(Deprovision):清理资源,避免浪费
Spring Cloud Open Service Broker 的价值在于:它已经帮你实现了 API 层的骨架——包括标准的控制器、领域模型和自动配置,你只需要关注业务逻辑,实现对应的服务代理接口即可。
⚠️ 注意:它不是服务本身,而是“服务的管理者”。你仍需对接真实的后端系统(如调用邮件 API、创建数据库账号等)。
3. 自动配置
要使用 Spring Cloud Open Service Broker,首先引入对应的 starter:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-open-service-broker</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
✅ 说明:
spring-cloud-starter-open-service-broker
:核心依赖,提供自动配置和基础组件。spring-boot-starter-web
:启用 Web 环境(基于 Spring MVC),也可替换为 WebFlux。
引入后,框架会自动配置好大部分组件(如默认的控制器、响应构建器等)。如果需要自定义行为,只需提供对应接口的 Bean 实现即可覆盖默认逻辑。
3.1 接口路径配置
默认情况下,所有服务代理接口挂载在根路径 /
下。这在实际项目中容易冲突。
最简单的做法是通过配置项修改基础路径:
spring:
cloud:
openservicebroker:
base-path: /broker
配置后,所有接口都会加上 /broker
前缀,例如:
- 获取目录:
GET /broker/v2/catalog
- 创建实例:
PUT /broker/v2/service_instances/{instance_id}
这样更清晰,也便于做统一的网关路由。
4. 服务代理实战示例
我们以“邮件服务代理”为例,演示如何使用该框架。目标是让云平台用户能通过标准流程创建并绑定一个邮件服务。
📌 示例中使用的
mailService
是一个模拟的内部服务,负责管理实例和凭据的生命周期。
4.1 服务目录(Catalog)
服务目录是平台发现服务的入口。你需要定义一个返回 Catalog
对象的 Spring Bean:
@Bean
public Catalog catalog() {
Plan mailFreePlan = Plan.builder()
.id("fd81196c-a414-43e5-bd81-1dbb082a3c55")
.name("mail-free-plan")
.description("Mail Service Free Plan")
.free(true)
.build();
ServiceDefinition serviceDefinition = ServiceDefinition.builder()
.id("b92c0ca7-c162-4029-b567-0d92978c0a97")
.name("mail-service")
.description("Mail Service")
.bindable(true)
.tags("mail", "service")
.plans(mailFreePlan)
.build();
return Catalog.builder()
.serviceDefinitions(serviceDefinition)
.build();
}
关键点:
ServiceDefinition
:定义服务元信息,bindable=true
表示支持绑定操作。Plan
:服务的“套餐”,可定义免费/付费等不同规格。id
字段必须全局唯一,建议使用 UUID。
配置完成后,访问 /broker/v2/catalog
即可看到服务列表:
curl http://localhost:8080/broker/v2/catalog
{
"services": [
{
"bindable": true,
"description": "Mail Service",
"id": "b92c0ca7-c162-4029-b567-0d92978c0a97",
"name": "mail-service",
"plans": [
{
"description": "Mail Service Free Plan",
"free": true,
"id": "fd81196c-a414-43e5-bd81-1dbb082a3c55",
"name": "mail-free-plan"
}
],
"tags": ["mail", "service"]
}
]
}
云平台会聚合所有注册的 Broker 目录,供用户选择。
4.2 服务创建(Provisioning)
创建服务实例需要实现 ServiceInstanceService
接口,核心是 createServiceInstance
方法:
@Override
public Mono<CreateServiceInstanceResponse> createServiceInstance(
CreateServiceInstanceRequest request) {
return Mono.just(request.getServiceInstanceId())
.flatMap(instanceId -> Mono.just(CreateServiceInstanceResponse.builder())
.flatMap(responseBuilder -> mailService.serviceInstanceExists(instanceId)
.flatMap(exists -> {
if (exists) {
return mailService.getServiceInstance(instanceId)
.flatMap(mailServiceInstance -> Mono.just(responseBuilder
.instanceExisted(true)
.dashboardUrl(mailServiceInstance.getDashboardUrl())
.build()));
} else {
return mailService.createServiceInstance(
instanceId, request.getServiceDefinitionId(), request.getPlanId())
.flatMap(mailServiceInstance -> Mono.just(responseBuilder
.instanceExisted(false)
.dashboardUrl(mailServiceInstance.getDashboardUrl())
.build()));
}
})));
}
逻辑说明:
- 检查实例是否已存在(幂等性要求)。
- 若不存在,则调用
mailService
创建新实例。 - 返回
dashboardUrl
,可为用户提供管理界面入口。
调用示例(创建实例):
curl -X PUT http://localhost:8080/broker/v2/service_instances/inst-123abc
-H 'Content-Type: application/json'
-d '{
"service_id": "b92c0ca7-c162-4029-b567-0d92978c0a97",
"plan_id": "fd81196c-a414-43e5-bd81-1dbb082a3c55"
}'
{"dashboard_url":"http://localhost:8080/mail-dashboard/inst-123abc"}
⚠️ 注意:
instance_id
由平台生成,必须全局唯一。service_id
和plan_id
必须与目录中的一致。
4.3 服务绑定(Binding)
绑定操作用于生成访问凭据。需实现 ServiceInstanceBindingService
接口:
@Override
public Mono<CreateServiceInstanceBindingResponse> createServiceInstanceBinding(
CreateServiceInstanceBindingRequest request) {
return Mono.just(CreateServiceInstanceAppBindingResponse.builder())
.flatMap(responseBuilder -> mailService.serviceBindingExists(
request.getServiceInstanceId(), request.getBindingId())
.flatMap(exists -> {
if (exists) {
return mailService.getServiceBinding(
request.getServiceInstanceId(), request.getBindingId())
.flatMap(serviceBinding -> Mono.just(responseBuilder
.bindingExisted(true)
.credentials(serviceBinding.getCredentials())
.build()));
} else {
return mailService.createServiceBinding(
request.getServiceInstanceId(), request.getBindingId())
.switchIfEmpty(Mono.error(
new ServiceInstanceDoesNotExistException(
request.getServiceInstanceId())))
.flatMap(mailServiceBinding -> Mono.just(responseBuilder
.bindingExisted(false)
.credentials(mailServiceBinding.getCredentials())
.build()));
}
}));
}
该方法返回包含连接信息的 credentials
,例如:
curl -X PUT
http://localhost:8080/broker/v2/service_instances/inst-123abc/service_bindings/bind-admin
-H 'Content-Type: application/json'
-d '{
"service_id": "b92c0ca7-c162-4029-b567-0d92978c0a97",
"plan_id": "fd81196c-a414-43e5-bd81-1dbb082a3c55"
}'
{
"credentials": {
"password": "bea65996-3871-4319-a6bb-a75df06c2a4d",
"uri": "http://localhost:8080/mail-system/inst-123abc",
"username": "admin"
}
}
平台会将这些凭据注入到应用的环境变量中,应用即可直接使用。
5. 接口安全
⚠️ 踩坑提醒:Open Service Broker API 规范本身不包含认证机制,因此 Spring Cloud Open Service Broker 也不会默认开启安全防护。这意味着你的接口默认是“裸奔”的!
生产环境必须加上认证,推荐方案:
- ✅ Basic Auth:简单粗暴,适合内部系统。
- ✅ OAuth 2.0:更安全,适合多租户或对外暴露的场景。
实现方式:直接集成 Spring Security。例如,添加 Basic Auth:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/broker/**").authenticated()
.anyRequest().permitAll()
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
这样,所有 /broker/**
接口都会要求 401 Unauthorized
认证,未通过则拒绝访问。
6. 总结
通过本文,你应该已经掌握:
- Open Service Broker API 的核心价值:标准化云平台与后端服务的对接。
- Spring Cloud Open Service Broker 如何帮你快速实现规范,只需关注业务逻辑。
- 关键接口(目录、创建、绑定)的实现方式与调用流程。
- 生产环境必须手动添加安全防护,避免接口暴露风险。
框架本身简洁高效,踩坑点少,适合快速集成自有服务到云平台。
💡 源码已托管至 GitHub:https://github.com/your-repo/spring-cloud-open-service-broker-demo