-
Notifications
You must be signed in to change notification settings - Fork 7
spring integration leader starter
Add the following module as a dependency:
<dependency>
<groupId>com.mimacom.spring</groupId>
<artifactId>spring-integration-leader-starter</artifactId>
<version>xxx</version>
</dependency>
spring-integration-leader-starter` is only going to configure itself if one of the following technologies is available and configured
- Zookeeper
- Hazelcast
- Lock-Registry
Info: If multiple of the mentioned providers are configured then the first one wins (as ordered as in the list above). However you can explicitly define the provider type using the following property:
spring-integration.leader.type=<provider>
. Whereas<provider>
can be 'zookeeper', 'hazelcast' or 'lock-registry'
Add the following dependency to your project:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-zookeeper</artifactId>
</dependency>
Provide a CuratorFramework
bean by using a spring-boot auto-configuration aware module such as the following:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-zookeeper-core</artifactId>
</dependency>
... or manually define the bean
@Configuration
public class MyZookeeperConfiguration {
@Bean
CuratorFrameworkFactoryBean curatorFramework() {
return new CuratorFrameworkFactoryBean("localhost:2181");
}
}
CuratorFrameworkFactoryBean
is part of thespring-integration-zookeeper
module
The zookeeper.path property defined where the zookeeper leaders are going to store their information
spring-integration:
leader:
zookeeper:
path: /custom/zookeeper/path
If no path has been defined spring-integration-leader-starter is going to build the path like this
- If
spring.application.name
has been defined:/spring/leader/<spring.application.name>/
- If no
spring.application.name
has been defined:/spring/leader/default/
Add the following dependency to your project:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-hazelcast</artifactId>
</dependency>
Provide a HazelcastInstance
by defining it manually or let the HazelcastAutoConfiguration
from the spring-boot-autoconfigure
module define it for you.
Provide a LockRegistry
Example based on a JdbcLockRegistry
@Configuration
class JdbcLockRegistryConfiguration {
private final DataSource dataSource;
JdbcLockRegistryConfiguration(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public DefaultLockRepository lockRepository() {
return new DefaultLockRepository(this.dataSource);
}
@Bean
public LockRegistry lockRegistry() {
return new JdbcLockRegistry(this.lockRepository());
}
}
You can define that some of your integration endpoints become "leader-aware" by declaring their endpoint role in your spring configuration file. The configured endpoints are then not going to "autostart" on startup instead they wait until the application has become the leader (org.springframework.integration.leader.event.OnGrantedEvent
) and if so the Endpoints are started. Visa-verca if the application's leadship has been revoked (org.springframework.integration.leader.event.OnRevokedEvent
) the configured Endpoints are then gracefully stopped.
Example:
In your application.[yml|property]
define the endpoint-bean-id in the key: spring-integration.leader-aware.endpoints
spring-integration:
leader:
roles: my-flow
@Configuration
public class FlowExampleConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(FlowExampleConfig.class);
@Bean
IntegrationFlow sampleIntegrationFlow() {
return IntegrationFlows
.from(() -> UUID.randomUUID().toString(), c -> c
.role("my-flow")
.poller(p -> p.fixedDelay(1000))
.autoStartup(false))
.handle((GenericHandler<String>) (payload, headers) -> {
LOGGER.info("Handle Message: {}", payload);
return null;
})
.get();
}
}
Hint: spring-integration-leader-start will automatically disable the endpoint's auto-start behaviour if that endpoint's role is configured as a leader-aware role
In the above example if we'd start multiple instances of the application only one - the leader - executes the sampleIntegrationFlow
once it received the Leader OnGrantedEvent
(see org.springframework.integration.support.SmartLifecycleRoleController
)
Decorate an method with the LeaderAware
annotation to make sure it is only called if the associated role is currently the leader.
Example:
spring-integration:
leader:
roles: my-role
@Configuration
public class SchedulerConfig {
@Scheduled(....)
@LeaderAware("my-role")
void sampleScheduler() {
// do something
}
}
spring-integration-leader-starter creates a LeaderProvider
for every defined spring-integration.leader.role
. In order to check manually whether a certain role has the leader-ship inject the LeaderProvider in your bean by using a qualifier
Bean-Name: <role>_leaderProvider
Example:
spring-integration:
leader:
roles: my-role
@Configuration
public class SchedulerConfig {
@Autowired
@Qualifier("my-role_LeaderProvider")
private LeaderProvider myRoleLeaderProvider;
@Scheduled(....)
void sampleScheduler() {
if (!this.myRoleLeaderProvider.getContext().isLeader()){
return;
}
// do something
}
}
A simple Health Indicator is created that show whether the current application instance is the leader. You can disable the health indicator like any actuator based health indicator in your application.[yml|property]
using the key: management.health.leader.enabled
management:
health:
leader:
enabled: false