1. Обзор
В этом руководстве мы представим проект Spring Cloud Open Service Broker и узнаем, как реализовать Open Service Broker API .
Сначала мы углубимся в спецификацию Open Service Broker API. Затем мы узнаем, как использовать Spring Cloud Open Service Broker для создания приложений, реализующих спецификации API.
Наконец, мы рассмотрим, какие механизмы безопасности мы можем использовать для защиты конечных точек нашего сервис-брокера.
2. Откройте API сервис-брокера
Проект Open Service Broker API позволяет нам быстро предоставлять услуги поддержки для наших приложений, работающих на облачных платформах, таких как Cloud Foundry и Kubernetes . По сути, спецификация API описывает набор конечных точек REST, через которые мы можем предоставлять эти услуги и подключаться к ним.
В частности, мы можем использовать сервис-брокеров на облачной платформе для:
- Рекламировать каталог сопроводительных услуг
- Предоставление экземпляров службы
- Создание и удаление привязок между вспомогательной службой и клиентским приложением.
- Деинициализация экземпляров службы
Spring Cloud Open Service Broker создает основу для реализации, совместимой с API Open Service Broker, предоставляя необходимые веб-контроллеры, объекты домена и конфигурацию . Кроме того, нам нужно будет придумать нашу бизнес-логику, реализовав соответствующие интерфейсы сервисного брокера .
3. Автоматическая настройка
Чтобы использовать Spring Cloud Open Service Broker в нашем приложении, нам нужно добавить соответствующий начальный
артефакт . Мы можем использовать Maven Central для поиска последней версии open-service-broker
starter .
Помимо облачного стартера, нам также потребуется включить веб-стартер Spring Boot и либо Spring WebFlux, либо Spring MVC, чтобы активировать автоматическую настройку:
<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>
Механизм автоматической настройки настраивает реализации по умолчанию для большинства компонентов, которые нам нужны для брокера служб. Если мы хотим, мы можем переопределить поведение по умолчанию, предоставив нашу собственную реализацию bean-компонентов open-service-broker
, связанных со Spring.
3.1. Конфигурация пути к конечным точкам Service Broker
По умолчанию контекстный путь, в котором зарегистрированы конечные точки брокера служб, — «/».
Если это не идеально и мы хотим его изменить, самый простой способ — установить свойство spring.cloud.openservicebroker.base-path
в свойствах нашего приложения или файле YAML:
spring:
cloud:
openservicebroker:
base-path: /broker
В этом случае, чтобы запросить конечные точки сервисного брокера, нам сначала нужно будет добавить к нашим запросам префикс /broker/
base-path.
4. Пример сервис-брокера
Давайте создадим приложение сервис-брокера, используя библиотеку Spring Cloud Open Service Broker, и изучим, как работает API.
В нашем примере мы будем использовать сервис-брокера для подготовки и подключения к резервной почтовой системе. Для простоты мы будем использовать фиктивный почтовый API, представленный в наших примерах кода.
4.1. Каталог услуг
Во- первых, чтобы контролировать, какие услуги предлагает наш брокер услуг, нам нужно определить каталог услуг . Чтобы быстро инициализировать каталог сервисов, в нашем примере мы предоставим bean-компонент Spring типа Catalog
:
@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();
}
Как показано выше, каталог услуг содержит метаданные, описывающие все доступные услуги, которые может предложить наш брокер услуг. Более того, определение сервиса намеренно широкое , поскольку оно может относиться к базе данных, очереди обмена сообщениями или, в нашем случае, к почтовому сервису .
Еще один ключевой момент заключается в том, что каждая услуга строится на основе планов, что является еще одним общим термином. По сути, каждый план может предлагать разные функции и стоить разную сумму .
В конце концов, каталог сервисов становится доступным для облачных платформ через конечную точку брокера сервисов /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"
]
}
]
}
Следовательно, облачные платформы будут запрашивать конечную точку каталога сервис-брокеров у всех сервис-брокеров, чтобы представить агрегированное представление каталогов сервисов.
4.2. Предоставление услуг
Как только мы запускаем рекламные услуги, нам также необходимо предоставить в нашем брокере механизмы для предоставления и управления их жизненным циклом в рамках облачной платформы.
Кроме того, то, что представляет собой подготовка, варьируется от брокера к брокеру. В некоторых случаях подготовка может включать развертывание пустых баз данных, создание брокера сообщений или просто предоставление учетной записи для доступа к внешним API .
С точки зрения терминологии службы, созданные брокером служб, будут называться экземплярами служб.
С помощью Spring Cloud Open Service Broker мы можем управлять жизненным циклом службы, реализуя интерфейс 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()));
}
})));
}
Здесь мы выделяем новую почтовую службу в наших внутренних сопоставлениях, если служба с таким же идентификатором экземпляра службы не существует, и предоставляем URL-адрес панели мониторинга. Мы можем рассматривать панель мониторинга как веб-интерфейс управления для нашего экземпляра службы.
Предоставление услуг доступно для облачных платформ через конечную точку /v2/service_instances/{instance_id}
:
curl -X PUT http://localhost:8080/broker/v2/service_instances/newsletter@foreach.com
-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/newsletter@foreach.com"}
Короче говоря, когда мы предоставляем новую услугу, нам нужно передать service_id
и plan_id,
объявленные в каталоге услуг . Кроме того, нам необходимо предоставить уникальный instance_id
, который наш сервисный брокер будет использовать в будущих запросах на привязку и отмену подготовки.
4.3. Привязка службы
После того, как мы предоставим услугу, нам нужно, чтобы наше клиентское приложение начало взаимодействовать с ней. С точки зрения брокера служб это называется привязкой службы.
Подобно экземплярам службы и планам, мы должны рассматривать привязку как еще одну гибкую абстракцию, которую мы можем использовать в нашем брокере службы. Как правило, мы предоставляем привязки службы для предоставления учетных данных, используемых для доступа к экземпляру службы .
В нашем примере, если в рекламируемом сервисе для поля bindable
задано значение true
, наш брокер сервисов должен предоставить реализацию интерфейса ServiceInstanceBindingService
. В противном случае облачные платформы не будут вызывать методы привязки службы из нашего брокера служб.
Давайте обработаем запросы на создание привязки службы, предоставив реализацию метода createServiceInstanceBinding
:
@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()));
}
}));
}
Вышеприведенный код генерирует уникальный набор учетных данных — имя пользователя, пароль и URI, — с помощью которых мы можем подключиться и аутентифицироваться в нашем новом экземпляре почтовой службы.
Платформа Spring Cloud Open Service Broker предоставляет операции привязки службы через конечную точку /v2/service_instances/{instance_id}/service_bindings/{binding_id}
:
curl -X PUT
http://localhost:8080/broker/v2/service_instances/newsletter@foreach.com/service_bindings/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/newsletter@foreach.com",
"username": "admin"
}
}
Как и при подготовке экземпляра службы, мы используем service_id
и plan_id,
объявленные в каталоге услуг в нашем запросе на привязку. Кроме того, мы также передаем уникальный binding_id
, который брокер использует в качестве имени пользователя для нашего набора учетных данных.
5. Безопасность API сервис-брокера
Обычно, когда сервис-брокеры и облачные платформы взаимодействуют друг с другом, требуется механизм аутентификации.
К сожалению, спецификация Open Service Broker API в настоящее время не охватывает часть проверки подлинности для конечных точек сервисного брокера. Из-за этого библиотека Spring Cloud Open Service Broker не реализует никакой конфигурации безопасности.
К счастью, если нам нужно защитить конечные точки нашего сервис-брокера, мы можем быстро использовать Spring Security, чтобы внедрить обычную аутентификацию или механизм OAuth 2.0 . В этом случае мы должны аутентифицировать все запросы сервис-брокера, используя выбранный нами механизм аутентификации, и возвращать ответ 401 Unauthorized
, если аутентификация не удалась.
6. Заключение
В этой статье мы рассмотрели проект Spring Cloud Open Service Broker.
Во-первых, мы узнали, что такое Open Service Broker API и как он позволяет нам предоставлять резервные службы и подключаться к ним. Впоследствии мы увидели, как быстро создать проект, совместимый с API Service Broker, с помощью библиотеки Spring Cloud Open Service Broker.
Наконец, мы обсудили, как мы можем защитить конечные точки нашего сервис-брокера с помощью Spring Security.
Как всегда, исходный код этого руководства доступен на GitHub .