Class SpringCloudAutoConfiguration.ConnectorConfiguration
- Enclosing class:
SpringCloudAutoConfiguration
axon.springcloud.enabled is set to false.
Nested so that the property switches these beans off while leaving
SpringCloudAutoConfiguration.disableSpringCloudConfigurationEnhancer() reachable — a class-level condition would switch that off too,
and the service-loaded enhancer would go on registering a connector regardless.
- Since:
- 5.4.0
- Author:
- Allard Buijze
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionorg.springframework.web.client.RestClientBean creation method for theRestClientused to ask other instances for their capabilities.axoniqSpringCloudCapabilityDiscoveryMode(org.springframework.web.client.RestClient restClient, SpringCloudProperties properties) Bean creation method for theCapabilityDiscoveryModeused to learn what each discovered instance handles.Bean creation method for the controller receiving commands from other members.Bean creation method for theExecutorServicediscovery rounds, and the capability requests within them, run on.Bean creation method for theExecutorthe blocking HTTP exchanges with other members run on.axoniqSpringCloudIncomingCommandInvoker(SpringCloudMemberDiscovery discovery, org.springframework.beans.factory.ObjectProvider<MessageConverter> converterProvider) Bean creation method for theIncomingCommandInvokerhandling commands sent by other members.axoniqSpringCloudIncomingQueryInvoker(SpringCloudMemberDiscovery discovery, org.springframework.beans.factory.ObjectProvider<MessageConverter> converterProvider) Bean creation method for theIncomingQueryInvokeranswering queries sent by other members.Bean creation method for theExecutorthe keep-alive of each subscription being answered is written on.Bean creation method for the controller serving this application's capabilities to other members.axoniqSpringCloudMemberDiscovery(org.springframework.beans.factory.ObjectProvider<org.springframework.cloud.client.discovery.DiscoveryClient> discoveryClientProvider, CapabilityDiscoveryMode discoveryMode, org.springframework.beans.factory.ObjectProvider<Predicate<org.springframework.cloud.client.ServiceInstance>> instanceFilterProvider, SpringCloudProperties properties, ExecutorService discoveryExecutor, ScheduledExecutorService scheduler) Bean creation method for theSpringCloudMemberDiscoverymaintaining the routing ring from what Spring Cloud Discovery reports.org.springframework.context.ApplicationListener<org.springframework.context.ApplicationEvent> Bean creation method for theApplicationListenerstarting a membership round whenever Spring Cloud Discovery signals that the instances it reports may have changed.axoniqSpringCloudQueryController(IncomingQueryInvoker invoker, ScheduledExecutorService scheduler, Executor keepAliveExecutor, SpringCloudProperties properties) Bean creation method for the controller answering queries from other members.org.springframework.web.client.RestClientaxoniqSpringCloudQueryRestClient(org.springframework.beans.factory.ObjectProvider<org.springframework.web.client.RestClient.Builder> builderProvider) Bean creation method for theRestClientused to send queries and subscription queries to other members.Bean creation method for theScheduledExecutorServicedeciding when a query's deadline has passed, when a subscription has been silent for too long, and when a subscription being answered is due a keep-alive.axoniqSpringCloudRemoteCommandDispatcher(org.springframework.web.client.RestClient restClient, Executor executor, SpringCloudProperties properties, org.springframework.beans.factory.ObjectProvider<MessageConverter> converterProvider) Bean creation method for theRemoteCommandDispatchersending commands to other members.axoniqSpringCloudRemoteQueryDispatcher(org.springframework.web.client.RestClient restClient, Executor executor, ScheduledExecutorService scheduler, MessageConverter converter, SpringCloudProperties properties) Bean creation method for theRemoteQueryDispatchersending queries to other members.org.springframework.web.client.RestClientaxoniqSpringCloudRestClient(org.springframework.beans.factory.ObjectProvider<org.springframework.web.client.RestClient.Builder> builderProvider, SpringCloudProperties properties) Bean creation method for theRestClientused to send commands to other members.org.springframework.context.SmartLifecycleaxoniqSpringCloudShutdownLifecycle(org.springframework.beans.factory.ObjectProvider<AxonConfiguration> configuration, IncomingQueryInvoker invoker) Announces this member leaving on the subscription queries it answers, before the web server stops serving their streams.
-
Constructor Details
-
ConnectorConfiguration
public ConnectorConfiguration()
-
-
Method Details
-
axoniqSpringCloudRestClient
@Bean("axoniqSpringCloudRestClient") @ConditionalOnMissingBean(name="axoniqSpringCloudRestClient") public org.springframework.web.client.RestClient axoniqSpringCloudRestClient(org.springframework.beans.factory.ObjectProvider<org.springframework.web.client.RestClient.Builder> builderProvider, SpringCloudProperties properties) Bean creation method for theRestClientused to send commands to other members.Built from the application's own
RestClient.Builderwhen it has one, so that whatever it configured there — a load balancer, authentication, timeouts — applies to inter-member traffic as well. When the application supplies no builder, the client is given timeouts of its own: without them a member that accepts a connection and then answers nothing holds the sending thread for as long as the operating system allows, outliving the dispatcher's own reply deadline, which bounds the returned future but not the exchange behind it.- Parameters:
builderProvider- provides the application'sRestClient.Builder, if it has oneproperties- the Spring Cloud connector specific properties set by the application- Returns:
- the client used to reach other members of the cluster
-
axoniqSpringCloudQueryRestClient
@Bean("axoniqSpringCloudQueryRestClient") @ConditionalOnMissingBean(name="axoniqSpringCloudQueryRestClient") public org.springframework.web.client.RestClient axoniqSpringCloudQueryRestClient(org.springframework.beans.factory.ObjectProvider<org.springframework.web.client.RestClient.Builder> builderProvider) Bean creation method for theRestClientused to send queries and subscription queries to other members.Built from the application's own
RestClient.Builderwhen it has one, keeping what it configured there, such as interceptors adding authentication, but always on a transport of its own: a JDK client with a connect timeout and no read timeout, which opens a connection per stream rather than borrowing one from a bounded pool. The dispatcher bounds the streams itself, with a deadline per query and a silence check per subscription.Because the transport is this client's own, transport settings of the application's client do not reach it, such as an SSL bundle configured for it or a custom request factory on the builder. Settings the JVM applies to every connection still do. An application whose members trust each other through an SSL bundle, or authenticate each other with client certificates, defines a bean named
SpringCloudAutoConfiguration.QUERY_REST_CLIENT_BEANitself, keeping it free of a read timeout and of a bounded connection pool. The same holds for the client namedSpringCloudAutoConfiguration.CAPABILITIES_REST_CLIENT_BEAN, which is built without the application's builder altogether.- Parameters:
builderProvider- provides the application'sRestClient.Builder, if it has one- Returns:
- the client used to send queries and subscription queries to other members
-
axoniqSpringCloudCapabilitiesRestClient
@Bean("axoniqSpringCloudCapabilitiesRestClient") @ConditionalOnMissingBean(name="axoniqSpringCloudCapabilitiesRestClient") public org.springframework.web.client.RestClient axoniqSpringCloudCapabilitiesRestClient(SpringCloudProperties properties) Bean creation method for theRestClientused to ask other instances for their capabilities.Separate from the client commands are sent with, because the two need opposite deadlines. A command may legitimately take as long as the handler needs, while a capabilities request happens on every discovery round and must not outlast it — one unresponsive instance would otherwise hold up the round that rebuilds the routing ring for every member.
- Parameters:
properties- the connector's properties- Returns:
- the client used to ask other instances for their capabilities
-
axoniqSpringCloudCapabilityDiscoveryMode
@Bean @ConditionalOnMissingBean public CapabilityDiscoveryMode axoniqSpringCloudCapabilityDiscoveryMode(@Qualifier("axoniqSpringCloudCapabilitiesRestClient") org.springframework.web.client.RestClient restClient, SpringCloudProperties properties) Bean creation method for theCapabilityDiscoveryModeused to learn what each discovered instance handles.Combines the REST mode — the only way capabilities can travel, since service instance metadata is fixed at registration time — with the ignore list that keeps unrelated services from being asked on every heartbeat.
- Parameters:
restClient- the client used to reach other membersproperties- the connector's properties- Returns:
- the mode used to discover the capabilities of other members
-
axoniqSpringCloudMemberDiscovery
@Bean @ConditionalOnMissingBean public SpringCloudMemberDiscovery axoniqSpringCloudMemberDiscovery(org.springframework.beans.factory.ObjectProvider<org.springframework.cloud.client.discovery.DiscoveryClient> discoveryClientProvider, CapabilityDiscoveryMode discoveryMode, org.springframework.beans.factory.ObjectProvider<Predicate<org.springframework.cloud.client.ServiceInstance>> instanceFilterProvider, SpringCloudProperties properties, @Qualifier("axoniqSpringCloudDiscoveryExecutor") ExecutorService discoveryExecutor, @Qualifier("axoniqSpringCloudQueryScheduler") ScheduledExecutorService scheduler) Bean creation method for theSpringCloudMemberDiscoverymaintaining the routing ring from what Spring Cloud Discovery reports.An application can narrow which discovered instances are considered at all by contributing a
Predicate<ServiceInstance>bean. That is worth doing on a registry holding many services: instances rejected by the predicate are never asked for their capabilities, which is cheaper than letting the ignore list learn about them one heartbeat at a time. Every instance is considered when no such bean is present.Capabilities are refreshed every
SpringCloudProperties.getCapabilitiesRefreshInterval(), as decided on thequery scheduler. That scheduler only hands the refresh to thediscovery executor, which is where the requests are made, so nothing on it blocks.- Parameters:
discoveryClientProvider- provides the client reporting the service instances making up the clusterdiscoveryMode- the mode used to discover the capabilities of other membersinstanceFilterProvider- provides the filter deciding which discovered instances are consideredproperties- the connector's propertiesdiscoveryExecutor- the executor discovery rounds and their capability requests run onscheduler- the scheduler deciding when capabilities are due a refresh- Returns:
- the discovery maintaining the routing ring
-
axoniqSpringCloudDiscoveryExecutor
@Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudDiscoveryExecutor") @ConditionalOnMissingBean(name="axoniqSpringCloudDiscoveryExecutor") public ExecutorService axoniqSpringCloudDiscoveryExecutor()Bean creation method for theExecutorServicediscovery rounds, and the capability requests within them, run on.A virtual-thread-per-task executor by default, as the work on it is blocking HTTP calls, one per discovered instance, concurrently. An application can supply its own under the "axoniqSpringCloudDiscoveryExecutor" name. A round waits for the requests it makes, so that executor must run more than one task at a time.
Shut down with
shutdownNowrather than theExecutorService.close()Spring would infer, so that shutting down does not wait for a round still asking an instance that no longer answers.- Returns:
- the executor discovery rounds run on
-
axoniqSpringCloudDispatchExecutor
@Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudDispatchExecutor") @ConditionalOnMissingBean(name="axoniqSpringCloudDispatchExecutor") public ExecutorService axoniqSpringCloudDispatchExecutor()Bean creation method for theExecutorthe blocking HTTP exchanges with other members run on.A virtual-thread-per-task executor, because the work on it is a blocking HTTP call and nothing else. Sizing a platform thread pool for that would cap the messages this member can have in flight for no reason other than the pool's own size.
Shut down with
shutdownNowrather than the destroy method Spring would infer. That would beExecutorService.close(), which waits for every task to finish — and a task here is the reading of a query's response stream, which lasts as long as the answering member keeps it open. Shutting down the application would then wait on members it is no longer talking to. The connector's own shutdown already waits for queries still in flight, in theOUTBOUND_QUERY_CONNECTORSphase, so by the time this runs the threads left are the ones nothing is waiting for.- Returns:
- the executor inter-member dispatches run on
-
axoniqSpringCloudQueryScheduler
@Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudQueryScheduler") @ConditionalOnMissingBean(name="axoniqSpringCloudQueryScheduler") public ScheduledExecutorService axoniqSpringCloudQueryScheduler()Bean creation method for theScheduledExecutorServicedeciding when a query's deadline has passed, when a subscription has been silent for too long, and when a subscription being answered is due a keep-alive.A cancelled deadline is removed from its queue rather than left to elapse, so a query answered promptly does not keep its responses reachable until the deadline would have fired.
A single thread carries all of it, which it can because nothing scheduled here blocks: the work is deciding that something is due, and the one due thing that blocks -- writing a keep-alive to a subscriber -- is handed to
axoniqSpringCloudKeepAliveExecutor()instead.- Returns:
- the scheduler query timing runs on
-
axoniqSpringCloudRemoteCommandDispatcher
@Bean @ConditionalOnMissingBean public RemoteCommandDispatcher axoniqSpringCloudRemoteCommandDispatcher(@Qualifier("axoniqSpringCloudRestClient") org.springframework.web.client.RestClient restClient, @Qualifier("axoniqSpringCloudDispatchExecutor") Executor executor, SpringCloudProperties properties, org.springframework.beans.factory.ObjectProvider<MessageConverter> converterProvider) Bean creation method for theRemoteCommandDispatchersending commands to other members.- Parameters:
restClient- the client used to reach other membersexecutor- the executor the blocking HTTP exchanges run onproperties- the connector's propertiesconverterProvider- provides theMessageConverter, if one is available- Returns:
- the dispatcher sending commands to other members
-
axoniqSpringCloudCommandController
@Bean @ConditionalOnMissingBean @ConditionalOnWebApplication(type=SERVLET) public SpringCloudCommandController axoniqSpringCloudCommandController(IncomingCommandInvoker invoker) Bean creation method for the controller receiving commands from other members.- Parameters:
invoker- the invoker handling commands sent by other members- Returns:
- the controller receiving commands from other members
-
axoniqSpringCloudShutdownLifecycle
@Bean public org.springframework.context.SmartLifecycle axoniqSpringCloudShutdownLifecycle(org.springframework.beans.factory.ObjectProvider<AxonConfiguration> configuration, IncomingQueryInvoker invoker) Announces this member leaving on the subscription queries it answers, before the web server stops serving their streams.- Parameters:
configuration- provides the configuration holding the streaming event processors to stop firstinvoker- the invoker answering the subscriptions to announce this member leaving on- Returns:
- the lifecycle announcing this member leaving on shutdown
-
axoniqSpringCloudRemoteQueryDispatcher
@Bean @ConditionalOnMissingBean public RemoteQueryDispatcher axoniqSpringCloudRemoteQueryDispatcher(@Qualifier("axoniqSpringCloudQueryRestClient") org.springframework.web.client.RestClient restClient, @Qualifier("axoniqSpringCloudDispatchExecutor") Executor executor, @Qualifier("axoniqSpringCloudQueryScheduler") ScheduledExecutorService scheduler, MessageConverter converter, SpringCloudProperties properties) Bean creation method for theRemoteQueryDispatchersending queries to other members.- Parameters:
restClient- the client sending the queries and subscription queriesexecutor- the executor each query's response stream is read onscheduler- the scheduler each query's deadline runs onconverter- the converter the events of a query's response stream are read withproperties- the connector's properties- Returns:
- the dispatcher sending queries to other members
-
axoniqSpringCloudQueryController
@Bean @ConditionalOnMissingBean @ConditionalOnWebApplication(type=SERVLET) public SpringCloudQueryController axoniqSpringCloudQueryController(IncomingQueryInvoker invoker, @Qualifier("axoniqSpringCloudQueryScheduler") ScheduledExecutorService scheduler, @Qualifier("axoniqSpringCloudKeepAliveExecutor") Executor keepAliveExecutor, SpringCloudProperties properties) Bean creation method for the controller answering queries from other members.- Parameters:
invoker- the invoker answering queries sent by other membersscheduler- the scheduler deciding when each open subscription is due a keep-alivekeepAliveExecutor- the executor those keep-alives are written onproperties- the connector's properties- Returns:
- the controller answering queries from other members
-
axoniqSpringCloudKeepAliveExecutor
@Bean(destroyMethod="shutdownNow", name="axoniqSpringCloudKeepAliveExecutor") @ConditionalOnMissingBean(name="axoniqSpringCloudKeepAliveExecutor") @ConditionalOnWebApplication(type=SERVLET) public ExecutorService axoniqSpringCloudKeepAliveExecutor()Bean creation method for theExecutorthe keep-alive of each subscription being answered is written on.Separate from the scheduler that decides when a keep-alive is due, because writing one is a blocking write to a single subscriber and deciding it is due is not. A subscriber that has stopped reading without closing blocks its write until the connection gives way; were that the scheduler's thread, it would hold up every other subscription's keep-alive and every dispatched query's deadline with it.
A virtual-thread-per-task executor, for the same reason the dispatch executor is one: the work is a blocking write and nothing else, and sizing a platform thread pool for it would cap the subscriptions this member can answer at the pool's own size.
- Returns:
- the executor subscription keep-alives are written on
-
axoniqSpringCloudMemberCapabilitiesController
@Bean @ConditionalOnMissingBean @ConditionalOnWebApplication(type=SERVLET) public MemberCapabilitiesController axoniqSpringCloudMemberCapabilitiesController(CapabilityDiscoveryMode discoveryMode) Bean creation method for the controller serving this application's capabilities to other members.- Parameters:
discoveryMode- the mode holding this application's own capabilities- Returns:
- the controller serving this application's capabilities
-