5. 服务绑定

Service Broker 可以通过服务绑定向服务实例的使用者提供信息。 服务绑定通常用于向应用程序公开服务实例资源的凭据。spring-doc.cn

如果该服务目录中任何计划的字段设置为 ,则 Service Broker 必须提供 ServiceInstanceBindingService 接口的实现。 否则,平台不会调用 Service Broker 的绑定方法,并且可以使用此接口的默认实现。 每个方法都接收一个 Java 对象参数,该参数包含来自平台的请求的所有详细信息,并返回一个 Java 对象值,该值向平台提供操作的详细信息。bindabletruespring-doc.cn

服务绑定的 create 和 delete 操作可以同步或异步执行。spring-doc.cn

  • 当 Service Broker 同步创建或删除服务绑定时,相应的接口方法应仅在操作成功完成或发生故障时阻止并返回对平台的响应。spring-doc.cn

  • 异步执行操作时,Service Broker 可以在操作完成之前向平台返回响应,并在响应中指示操作正在进行中。 当指示异步操作时,平台会轮询 Service Broker 以获取操作的状态。spring-doc.cn

5.1. 服务绑定创建

Service Broker 必须提供 createServiceInstanceBinding() 方法的实现。spring-doc.cn

支持两种类型的绑定:spring-doc.cn

  • 应用程序绑定可用于向应用程序提供凭据、日志耗尽和卷服务。spring-doc.cn

  • 路由绑定可用于为平台提供路由,以便在代理请求时使用。spring-doc.cn

此方法的响应允许返回两种 Java 对象类型之一,以反映支持的两种类型的绑定。spring-doc.cn

Service Broker 可以为所有绑定请求生成一组凭据,也可以为每个绑定请求提供唯一凭据。spring-doc.cn

5.1.1. 事件注册中心

您可以使用事件进一步自定义服务绑定创建。 为此,请执行以下操作:spring-doc.cn

  1. 自动装配 CreateServiceInstanceBindingEventFlowRegistry Bean。spring-doc.cn

  2. 使用 addInitializationFlow()、addCompletionFlow()addErrorFlow() 方法之一注册自定义反应流,以便在创建服务绑定的各个阶段运行。spring-doc.cn

5.2. 服务绑定删除

Service Broker 必须提供 deleteServiceInstanceBinding() 方法的实现。spring-doc.cn

在 create 操作中预置的任何凭证都应由 delete 操作取消预置。spring-doc.cn

5.2.1. 事件注册表

您可以使用事件进一步自定义服务绑定删除。 为此,请执行以下操作: .自动装配 DeleteServiceInstanceBindingEventFlowRegistry Bean。spring-doc.cn

  1. 使用 addInitializationFlow()、addCompletionFlow()addErrorFlow() 方法之一注册自定义反应流,以便在删除服务绑定的各个阶段运行。spring-doc.cn

5.3. 服务绑定操作状态检索

如果任何创建或删除操作可以向平台返回异步“operation in progress”响应,则 Service Broker 必须提供 getLastOperation() 方法的实现。否则,平台永远不会调用此方法,并且可以使用接口中的默认实现。spring-doc.cn

平台会轮询 Service Broker 的此方法,以查找正在进行异步操作的服务实例,直到 Service Broker 指示操作已成功完成或发生故障。spring-doc.cn

5.3.1. 事件注册中心

您可以使用事件进一步自定义服务绑定上次操作请求。 为此,请执行以下操作: .自动装配 AsyncOperationServiceInstanceBindingEventFlowRegistry Bean。spring-doc.cn

  1. 使用 addInitializationFlow()、addCompletionFlow()addErrorFlow() 方法之一注册自定义反应流,以便在上次操作检索的各个阶段运行。spring-doc.cn

5.4. 服务绑定检索

如果该字段在服务目录中设置为 ,则服务目录必须提供 getServiceInstanceBinding() 方法的实现。 否则,平台永远不会调用此方法,并且可以使用接口中的默认实现。bindings_retrievabletruespring-doc.cn

Service Broker 负责维护支持检索操作所需的任何服务绑定状态。spring-doc.cn

5.5. 示例实现

以下示例实现服务绑定:spring-doc.cn

package com.example.servicebroker;

import reactor.core.publisher.Mono;

import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceAppBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetServiceInstanceAppBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.GetServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.service.ServiceInstanceBindingService;
import org.springframework.stereotype.Service;

@Service
public class ExampleServiceBindingService implements ServiceInstanceBindingService {

	@Override
	public Mono<CreateServiceInstanceBindingResponse> createServiceInstanceBinding(CreateServiceInstanceBindingRequest request) {
		String serviceInstanceId = request.getServiceInstanceId();
		String bindingId = request.getBindingId();

		//
		// create credentials and store for later retrieval
		//

		String url = new String(/* build a URL to access the service instance */);
		String bindingUsername = new String(/* create a user */);
		String bindingPassword = new String(/* create a password */);

		CreateServiceInstanceBindingResponse response = CreateServiceInstanceAppBindingResponse.builder()
				.credentials("url", url)
				.credentials("username", bindingUsername)
				.credentials("password", bindingPassword)
				.bindingExisted(false)
				.async(true)
				.build();

		return Mono.just(response);
	}

	@Override
	public Mono<DeleteServiceInstanceBindingResponse> deleteServiceInstanceBinding(DeleteServiceInstanceBindingRequest request) {
		String serviceInstanceId = request.getServiceInstanceId();
		String bindingId = request.getBindingId();

		//
		// delete any binding-specific credentials
		//

		return Mono.just(DeleteServiceInstanceBindingResponse.builder()
				.async(true)
				.build());
	}

	@Override
	public Mono<GetServiceInstanceBindingResponse> getServiceInstanceBinding(GetServiceInstanceBindingRequest request) {
		String serviceInstanceId = request.getServiceInstanceId();
		String bindingId = request.getBindingId();

		//
		// retrieve the details of the specified service binding
		//

		String url = new String(/* retrieved URL */);
		String bindingUsername = new String(/* retrieved user */);
		String bindingPassword = new String(/* retrieved password */);

		GetServiceInstanceBindingResponse response = GetServiceInstanceAppBindingResponse.builder()
				.credentials("username", bindingUsername)
				.credentials("password", bindingPassword)
				.credentials("url", url)
				.build();

		return Mono.just(response);
	}
}

5.6. 事件流配置示例

有多种方法可以配置服务绑定事件流。 一种选择是自动装配一个或多个注册表并直接与注册表交互。 另一个选项是为特定流定义 bean。 这些 bean 将被自动识别并添加到相应的注册表中。 最后一个选项是声明一个新的注册表 bean。 但是,请注意,定义新的注册表 Bean 会覆盖提供的自动配置。spring-doc.cn

5.6.1. 选项 1:Autowire 注册表

以下示例配置服务绑定事件流:spring-doc.cn

package com.example.servicebroker;

import reactor.core.publisher.Mono;

import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationRequest;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationResponse;
import org.springframework.cloud.servicebroker.service.events.AsyncOperationServiceInstanceBindingEventFlowRegistry;
import org.springframework.cloud.servicebroker.service.events.CreateServiceInstanceBindingEventFlowRegistry;
import org.springframework.cloud.servicebroker.service.events.DeleteServiceInstanceBindingEventFlowRegistry;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingInitializationFlow;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ExampleServiceBindingEventFlowsConfiguration {

	private final CreateServiceInstanceBindingEventFlowRegistry createRegistry;

	private final DeleteServiceInstanceBindingEventFlowRegistry deleteRegistry;

	private final AsyncOperationServiceInstanceBindingEventFlowRegistry asyncRegistry;

	public ExampleServiceBindingEventFlowsConfiguration(
			CreateServiceInstanceBindingEventFlowRegistry createRegistry,
			DeleteServiceInstanceBindingEventFlowRegistry deleteRegistry,
			AsyncOperationServiceInstanceBindingEventFlowRegistry asyncRegistry) {
		this.createRegistry = createRegistry;
		this.deleteRegistry = deleteRegistry;
		this.asyncRegistry = asyncRegistry;

		prepareCreateEventFlows()
				.then(prepareDeleteEventFlows())
				.then(prepareLastOperationEventFlows())
				.subscribe();
	}

	private Mono<Void> prepareCreateEventFlows() {
		return Mono.just(createRegistry)
				.map(registry -> registry.addInitializationFlow(new CreateServiceInstanceBindingInitializationFlow() {
					@Override
					public Mono<Void> initialize(CreateServiceInstanceBindingRequest request) {
						//
						// do something before the instance is created
						//
						return Mono.empty();
					}
				})
						.then(registry.addCompletionFlow(new CreateServiceInstanceBindingCompletionFlow() {
							@Override
							public Mono<Void> complete(CreateServiceInstanceBindingRequest request,
													   CreateServiceInstanceBindingResponse response) {
								//
								// do something after the instance is created
								//
								return Mono.empty();
							}
						}))
						.then(registry.addErrorFlow(new CreateServiceInstanceBindingErrorFlow() {
							@Override
							public Mono<Void> error(CreateServiceInstanceBindingRequest request, Throwable t) {
								//
								// do something if an error occurs while creating an instance
								//
								return Mono.empty();
							}
						})))
				.then();
	}

	private Mono<Void> prepareDeleteEventFlows() {
		return Mono.just(deleteRegistry)
				.map(registry -> registry.addInitializationFlow(new DeleteServiceInstanceBindingInitializationFlow() {
					@Override
					public Mono<Void> initialize(DeleteServiceInstanceBindingRequest request) {
						//
						// do something before the instance is deleted
						//
						return Mono.empty();
					}
				})
						.then(registry.addCompletionFlow(new DeleteServiceInstanceBindingCompletionFlow() {
							@Override
							public Mono<Void> complete(DeleteServiceInstanceBindingRequest request,
													   DeleteServiceInstanceBindingResponse response) {
								//
								// do something after the instance is deleted
								//
								return Mono.empty();
							}
						}))
						.then(registry.addErrorFlow(new DeleteServiceInstanceBindingErrorFlow() {
							@Override
							public Mono<Void> error(DeleteServiceInstanceBindingRequest request, Throwable t) {
								//
								// do something if an error occurs while deleting an instance
								//
								return Mono.empty();
							}
						})))
				.then();
	}

	private Mono<Void> prepareLastOperationEventFlows() {
		return Mono.just(asyncRegistry)
				.map(registry -> registry.addInitializationFlow(new AsyncOperationServiceInstanceBindingInitializationFlow() {
					@Override
					public Mono<Void> initialize(GetLastServiceBindingOperationRequest request) {
						//
						// do something before the instance is deleted
						//
						return Mono.empty();
					}
				})
						.then(registry.addCompletionFlow(new AsyncOperationServiceInstanceBindingCompletionFlow() {
							@Override
							public Mono<Void> complete(GetLastServiceBindingOperationRequest request,
									GetLastServiceBindingOperationResponse response) {
								//
								// do something after the instance is deleted
								//
								return Mono.empty();
							}
						}))
						.then(registry.addErrorFlow(new AsyncOperationServiceInstanceBindingErrorFlow() {
							public Mono<Void> error(GetLastServiceBindingOperationRequest request, Throwable t) {
								//
								// do something if an error occurs while deleting an instance
								//
								return Mono.empty();
							}
						})))
				.then();
	}

}

5.6.2. 选项 2:事件流 Bean

(可选)您可以为各个流配置 bean,如下所示:spring-doc.cn

package com.example.servicebroker;

import reactor.core.publisher.Mono;

import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.CreateServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.binding.DeleteServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationRequest;
import org.springframework.cloud.servicebroker.model.binding.GetLastServiceBindingOperationResponse;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.AsyncOperationServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.CreateServiceInstanceBindingInitializationFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingCompletionFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingErrorFlow;
import org.springframework.cloud.servicebroker.service.events.flows.DeleteServiceInstanceBindingInitializationFlow;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ExampleServiceBindingEventFlowsConfiguration2 {

	//
	// Create Service Instance Binding flows
	//

	@Bean
	public CreateServiceInstanceBindingInitializationFlow createServiceInstanceBindingInitializationFlow() {
		return new CreateServiceInstanceBindingInitializationFlow() {
			@Override
			public Mono<Void> initialize(CreateServiceInstanceBindingRequest request) {
				//
				// do something before the service instance binding completes
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public CreateServiceInstanceBindingCompletionFlow createServiceInstanceBindingCompletionFlow() {
		return new CreateServiceInstanceBindingCompletionFlow() {
			@Override
			public Mono<Void> complete(CreateServiceInstanceBindingRequest request,
					CreateServiceInstanceBindingResponse response) {
				//
				// do something after the service instance binding completes
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public CreateServiceInstanceBindingErrorFlow createServiceInstanceBindingErrorFlow() {
		return new CreateServiceInstanceBindingErrorFlow() {
			@Override
			public Mono<Void> error(CreateServiceInstanceBindingRequest request, Throwable t) {
				//
				// do something if an error occurs while creating a service instance binding
				//
				return Mono.empty();
			}
		};
	}

	//
	// Delete Service Instance Binding flows
	//

	@Bean
	public DeleteServiceInstanceBindingInitializationFlow deleteServiceInstanceBindingInitializationFlow() {
		return new DeleteServiceInstanceBindingInitializationFlow() {
			@Override
			public Mono<Void> initialize(DeleteServiceInstanceBindingRequest request) {
				//
				// do something before the service instance binding is deleted
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public DeleteServiceInstanceBindingCompletionFlow deleteServiceInstanceBindingCompletionFlow() {
		return new DeleteServiceInstanceBindingCompletionFlow() {
			@Override
			public Mono<Void> complete(DeleteServiceInstanceBindingRequest request,
					DeleteServiceInstanceBindingResponse response) {
				//
				// do something after the service instance binding is deleted
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public DeleteServiceInstanceBindingErrorFlow deleteServiceInstanceBindingErrorFlow() {
		return new DeleteServiceInstanceBindingErrorFlow() {
			@Override
			public Mono<Void> error(DeleteServiceInstanceBindingRequest request, Throwable t) {
				//
				// do something if an error occurs while deleting a service instance binding
				//
				return Mono.empty();
			}
		};
	}

	//
	// Get Last Service Instance Binding Operation flows
	//

	@Bean
	public AsyncOperationServiceInstanceBindingInitializationFlow getLastOperationServiceInstanceBindingInitializationFlow() {
		return new AsyncOperationServiceInstanceBindingInitializationFlow() {
			@Override
			public Mono<Void> initialize(GetLastServiceBindingOperationRequest request) {
				//
				// do something before getting the last operation
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public AsyncOperationServiceInstanceBindingCompletionFlow getLastOperationServiceInstanceBindingCompletionFlow() {
		return new AsyncOperationServiceInstanceBindingCompletionFlow() {
			@Override
			public Mono<Void> complete(GetLastServiceBindingOperationRequest request,
					GetLastServiceBindingOperationResponse response) {
				//
				// do something after getting the last operation
				//
				return Mono.empty();
			}
		};
	}

	@Bean
	public AsyncOperationServiceInstanceBindingErrorFlow getLastOperationServiceInstanceBindingErrorFlow() {
		return new AsyncOperationServiceInstanceBindingErrorFlow() {
			@Override
			public Mono<Void> error(GetLastServiceBindingOperationRequest request, Throwable t) {
				//
				// do something if an error occurs while getting the last operation
				//
				return Mono.empty();
			}
		};
	}
}