【Pulsar】二次开发过程中遇到线程阻塞问题

在对Pulsar进行二次开发时,增加了消息查询功能,导致查询接口出现长时间阻塞。分析发现,问题可能源于ZooKeeper(ZK)操作的回调函数阻塞,原因是ZK查询和业务逻辑在同一线程执行。解决方案是将topic存在性检查与消息查询逻辑分离,避免在ZK回调中执行耗时操作。在后续开发中应注意避免在ZK回调中执行异步查询和长时间逻辑,确保线程资源的及时释放。

摘要

公司有用到pulsar,原有的功能不满足需求,所以进行了二次开发。增加的功能就是简单的消息查询,通过时间段、消息ID等参数查询消息内容,使用pulsar-admin的api提供了查询接口。

在测试的过程中发现查询接口会出现长时间阻塞,而且没办法恢复。

分析

增加的流程

  • 校验topic是否存在
  • 获取topic的所有订阅
  • 每个订阅开启一个readonly cursor
  • 通过cursor读取消息封装后返回给客户端

pulsar的所有模块基本都是异步的,通过CompletableFuture实现,因此就怀疑是这个原因导致线程出现了死锁。
通过jstack获取堆栈信息:
jstack pid
在这里插入图片描述
从上述图中可以看到zk的查询操作和业务操作出现了阻塞,相互等待。
而且执行业务的线程是metadata-store的线程,这就很奇怪。因为只有zk的操作才通过这个线程执行。在AbstractMetadataStore中可以看到,zk里初始化了只有一个线程的线程池负责zk的所有后续操作,执行查询后的回调函数。
在这里插入图片描述

在这里插入图片描述
上述execute方法就是通过初始化的线程池执行业务逻辑传递的回调函数。

通过上述的分析,基本可以确定到是zk执行的回调函数出现了阻塞,导致zk的线程池一直不能用,也就不能继续执行后续的zk查询等操作。

定位

知道了原因,后边定位就比较简单了。消息查询的时候有一个判断topic是否存在的逻辑,在这个逻辑中也有查询zk的行为。
之前的代码在判断topic是否存在后执行了消息查询的逻辑,而消息查询也涉及到zk的查询,消息查询使用了zk的线程,因此出现了阻塞。

解决

解决办法就是把topic的判断拆分出来。
在这里插入图片描述

后续

pulsar中zk的操作基本都是单线程的,而且全部都是异步操作,很容易出现这种阻塞的问题。在二次开发过程中,要注意:

  • 不在zk的查询回调函数中执行耗时长的逻辑。
  • 不在zk的查询回调里执行zk的查询逻辑。
  • 做好异常判断,及时释放线程资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值