spring integration leader jdbc无法解决

时间:2018-04-07 10:33:12

标签: spring spring-integration

我正在尝试使用JDBC在spring-integration中使用领导者选举。只要数据库已连接,它就可以工作。一旦删除数据库连接,领导者选举就会停止工作,并且该节点上的领导者信息保持不变。

据我了解代码,连接丢失时会抛出异常。领导者选举然后尝试删除数据库中的锁(当然这是不可能的),并抛出另一个异常并且执行程序服务停止运行。 (最后在LockRegistryLeaderInitiator中调用block()方法)

我是否必须对数据库断开连接做出反应?我必须配置一些东西吗?

重现的步骤:

  • 启动第一项服务
  • 检查它是领导者
  • 停止数据库
  • 该实例仍然是领导者
  • 再次启动数据库
  • 启动第二个实例
  • 现在都是领导者

依赖关系:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
</parent>
<dependency>
  <groupId>org.springframework.integration</groupId>
  <artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.integration</groupId>
  <artifactId>spring-integration-jdbc</artifactId>
</dependency>

LeaderElectionConfiguration

@Configuration
public class LeaderElectionConfiguration {

@Bean
public LockRegistry lockRegistry(LockRepository lockRepository) {
    return new JdbcLockRegistry(lockRepository);
}

@Bean
public DefaultLockRepository lockRepository(DataSource dataSource) {
    return new DefaultLockRepository(dataSource);
}

@Bean
public LockRegistryLeaderInitiator leaderInitiator(LockRegistry lockRegistry) {
    LockRegistryLeaderInitiator lockRegistryLeaderInitiator = new LockRegistryLeaderInitiator(lockRegistry);
    lockRegistryLeaderInitiator.start();
    return lockRegistryLeaderInitiator;
}

}

jdbc config:

spring:
  datasource:
    initialize: false
    url: jdbc:mysql://localhost:3306/whatever
    username: admin
    password: adminpw
    driver-class-name: com.mysql.cj.jdbc.Driver

1 个答案:

答案 0 :(得分:1)

我确认这是一个错误:https://jira.spring.io/browse/INT-4447

我们确实在LockRegistryLeaderInitiator中有一个代码:

catch (Exception e) {
                    if (this.locked) {
                        this.lock.unlock();
                        this.locked = false;
                        // The lock was broken and we are no longer leader
                        handleRevoked();
                        if (isRunning()) {
                            // Give it a chance to elect some other leader.
                            Thread.sleep(LockRegistryLeaderInitiator.this.busyWaitMillis);
                        }
                    }

我们必须处理来自unlock()的异常并撤销其结果。

作为一种解决方法,我建议您实施自己的(只需扩展现有的DefaultLockRepository就足够了)和try...catch() delete()中的unlock例外情况,以便让LockRegistryLeaderInitiator逻辑进入 SELECT date, userid FROM consumer.events WHERE Count(userid) > 1 ORDER BY date, userid 正常进行。