SpringBoot 1.5.4 版本和SpringBoot 2.7.18 在kafka重平衡对消费线程的处理方式略有差异

在1.5.4中SpringBoot对应的Spring kafka的版本

org.springframework.kafka:spring-kafka:1.1.6.RELEASE

在此版本的Spring对于kafka发生重平衡过程对消费线程的处理,会在awakeup之后打断消费线程,也就做优雅关闭的处理(设置消费线程的状态为interpred),具体的测试代码和现象如下

在消费session是15秒的基础下,我将业务的代码逻辑设置为100秒等待,显然这种情况会因为消费超时而发生重平衡,那么在较低版本的kafka的依赖支持上,那么会在执行awakeup之后执行消费线程的 interpret,具体的重平衡的效果会报错如下

这是因为在 org.springframework.kafka:spring-kafka:1.1.6.RELEASE中对kafka的重平衡,会先将所有的consumer的thread状态设置为interpred,具体的源码如下

所以在低版本的spring for kafka 中对于重平衡的处理,Spring 并不保证当前正在执行的消费线程能够正常执行完成,如果在过程中业务代码使用了Lock 、线程池可能会出现InterpretException的地方,那么业务执行就会被打断(比较致命),当然肯定很多人说一般应该避免非必要重平衡的发生,但是我现在的一个项目在重平衡过程中依然在消费订单,导致每一次的上下线,就会出现问题因为线程被中断

在2.7.18中SpringBoot对应的Spring kafka的版本是

org.springframework.kafka:spring-kafka:2.8.11

高版本的doStop的方法比较简单,kafka的支持 2.x的版本的代码更加的复杂

执行的流程是

  1. 检查isRunning() - 确保容器正在运行

  2. 注册StopCallback - 设置停止完成后的回调

  3. 设置running=false - 通知消费线程停止

  4. 调用wakeup() - 唤醒可能阻塞的消费线程

  5. 记录停止类型 - 标记为正常停止

  6. 消费线程检测到停止标志

  7. 完成当前消息处理

  8. 关闭consumer连接

  9. Future完成,触发StopCallback

  10. 执行回调,通知重平衡完成

对应的源码主要是

kotlin 复制代码
public void run() {
    ListenerUtils.setLogOnlyMetadata(this.containerProperties.isOnlyLogRecordMetadata());
    publishConsumerStartingEvent();
    this.consumerThread = Thread.currentThread();
    setupSeeks();
    KafkaUtils.setConsumerGroupId(this.consumerGroupId);
    this.count = 0;
    this.last = System.currentTimeMillis();
    initAssignedPartitions();
    publishConsumerStartedEvent();
    Throwable exitThrowable = null;
    while (isRunning()) {
       try {
          pollAndInvoke();
       }
       catch (NoOffsetForPartitionException nofpe) {
          this.fatalError = true;
          ListenerConsumer.this.logger.error(nofpe, "No offset and no reset policy");
          exitThrowable = nofpe;
          break;
       }
       catch (AuthenticationException | AuthorizationException ae) {
          if (this.authExceptionRetryInterval == null) {
             ListenerConsumer.this.logger.error(ae,
                   "Authentication/Authorization Exception and no authExceptionRetryInterval set");
             this.fatalError = true;
             exitThrowable = ae;
             break;
          }
          else {
             ListenerConsumer.this.logger.error(ae,
                   "Authentication/Authorization Exception, retrying in "
                         + this.authExceptionRetryInterval.toMillis() + " ms");
             // We can't pause/resume here, as KafkaConsumer doesn't take pausing
             // into account when committing, hence risk of being flooded with
             // GroupAuthorizationExceptions.
             // see: https://github.com/spring-projects/spring-kafka/pull/1337
             sleepFor(this.authExceptionRetryInterval);
          }
       }
       catch (FencedInstanceIdException fie) {
          this.fatalError = true;
          ListenerConsumer.this.logger.error(fie, "'" + ConsumerConfig.GROUP_INSTANCE_ID_CONFIG
                + "' has been fenced");
          exitThrowable = fie;
          break;
       }
       catch (StopAfterFenceException e) {
          this.logger.error(e, "Stopping container due to fencing");
          stop(false);
          exitThrowable = e;
       }
       catch (Error e) { // NOSONAR - rethrown
          this.logger.error(e, "Stopping container due to an Error");
          this.fatalError = true;
          wrapUp(e);
          throw e;
       }
       catch (Exception e) {
          handleConsumerException(e);
       }
       finally {
          clearThreadState();
       }
    }
    wrapUp(exitThrowable);
}

可见,在stop的时候 running直接退出,对于被invokeIfHaveRecords的数据会被等待执行完成 ,并不会影响正在执行的消费线程。

相关推荐
用户40993225021217 分钟前
BackgroundTasks 如何巧妙驾驭多任务并发?
后端·github·trae
ZLlllllll028 分钟前
常见的框架漏洞(Thinkphp,spring,Shiro)
java·后端·spring·常见的框架漏洞
ZS88538 分钟前
【AI】 Clickhouse MergeTree基本原理
后端
陈随易1 小时前
为VSCode扩展开发量身打造的UI库 - vscode-elements
前端·后端·程序员
Always_July1 小时前
java如何使用函数式编程优雅处理根据ID设置Name
后端
uhakadotcom1 小时前
Docker 入门教程
后端·面试·github
冒泡的肥皂1 小时前
2PL-事务并发控制
数据库·后端·mysql
天天摸鱼的java工程师2 小时前
面试必问的JVM垃圾收集机制详解
java·后端·面试
用户1512905452203 小时前
js获取当前日期时间及其它操作
后端