jetlinks / jetlinks-community

JetLinks 基于Java8,Spring Boot 2.x ,WebFlux,Netty,Vert.x,Reactor等开发, 是一个全响应式的企业级物联网平台。支持统一物模型管理,多种设备,多种厂家,统一管理。统一设备连接管理,多协议适配(TCP,MQTT,UDP,CoAP,HTTP等),屏蔽网络编程复杂性,灵活接入不同厂家不同协议等设备。实时数据处理,设备告警,消息通知,数据转发。地理位置,数据可视化等。能帮助你快速建立物联网相关业务系统。
https://www.jetlinks.cn/
Apache License 2.0
5.57k stars 1.67k forks source link

求助:遇到系统系统假死的问题 #477

Closed MoonBottle closed 5 months ago

MoonBottle commented 5 months ago

现象:系统登录接口超时

排查过程: 系统出现很多 TIMED_WAITING 状态的线程 image 初步怀疑是数据库出问题,然后发现 pgsql 确实有死锁,全部终止后,系统还是没恢复正常(登录超时) 依然有很多 TIMED_WAITING 状态的线程

zhou-hao commented 5 months ago

TIMED_WAITING 的线程通常没有什么问题。

  1. jetlinks版本
  2. jstack -l信息
zhou-hao commented 5 months ago

有没有什么特殊业务,是操作较大量数据的 flatMap,groupBy,window 等操作.

MoonBottle commented 5 months ago

有没有什么特殊业务,是操作较大量数据的 flatMap,groupBy,window 等操作.

有的,数据导出,历史数据曲线(1分钟一条)之类的需求有用到

zhou-hao commented 5 months ago

设置 并行度试试如: flatMap | groupBy(xxx,Integer.MAX_VALUE)

zhou-hao commented 5 months ago

https://github.com/jetlinks/jetlinks-community/blob/master/jetlinks-components/common-component/src/main/java/org/jetlinks/community/configuration/CommonConfiguration.java#L126 检查这里 有没有这个逻辑。

MoonBottle commented 5 months ago

2.0.0 版本

jstack 信息 1.txt

zhou-hao commented 5 months ago

2.0.0 版本

jstack 信息 1.txt

看上去并没有线程阻塞。

对比一下master pom.xml 的 reactor.version

MoonBottle commented 5 months ago

image 没有这个逻辑

zhou-hao commented 5 months ago

没有这个逻辑

增加这段逻辑。

MoonBottle commented 5 months ago

2.0.0 版本 jstack 信息 1.txt

看上去并没有线程阻塞。

对比一下master pom.xml 的 reactor.version

2020.0.22
zhou-hao commented 5 months ago

2.0.0 版本 jstack 信息 1.txt

看上去并没有线程阻塞。 对比一下master pom.xml 的 reactor.version

2020.0.22

修改为master的版本

MoonBottle commented 5 months ago

因为这个问题触发原因现在是未知的,我先改了观察观察,非常感谢

zhou-hao commented 5 months ago

因为这个问题触发原因现在是未知的,我先改了观察观察,非常感谢

已知的可能性:

  1. 有线程阻塞导致redis线程阻塞 (jstack看上去不像)
  2. reactor bug,不过看版本也不像。 https://github.com/reactor/reactor-core/issues/3621
  3. 有jvm级别的Error异常导致Flux被挂起。通过 Hooks.onOperatorError捕获并转换为RuntimeException
  4. flatMap 等操作符并行度设置不当导致Flux被挂起, 但是通常不会影响其他操作。
MoonBottle commented 5 months ago

看着 3 的可能性更大些,但奇怪的是也没有 block 的线程为什么会影响到登录接口超时

zhou-hao commented 5 months ago

看着 3 的可能性更大些,但奇怪的是也没有 block 的线程为什么会影响到登录接口超时

可以尝试调用其他接口,看是否也超时。

MoonBottle commented 5 months ago

version 接口可以调用 image

下面俩接口超时 api/system/config/amap api/menu/user-own/tree

MoonBottle commented 5 months ago

version 接口可以调用 image

下面俩接口超时 api/system/config/amap api/menu/user-own/tree

别的接口也试了下,也都是超时的情况

zhou-hao commented 5 months ago

那就更新再试试?

MoonBottle commented 5 months ago

嗯嗯,我先更新上去,观察观察

MoonBottle commented 5 months ago

昨天的改动更新上去之后还是会有假死的情况 触发条件是出现大量的死锁 image

并且发现在假死的情况下,查询 es 中的设备日志接口能正常调用

zhou-hao commented 5 months ago

昨天的改动更新上去之后还是会有假死的情况

触发条件是出现大量的死锁

image

并且发现在假死的情况下,查询 es 中的设备日志接口能正常调用

那就是数据库连接池耗尽呗。 检查哪里执行的这个sql操作。

MoonBottle commented 5 months ago

请教下,怎么以非事务的形式执行sql,也就是某些sql我可以不加锁

截图中的 sql 出现的地方挺多的,但奇怪的是之前的正常的,昨天突然不正常了

MoonBottle commented 5 months ago
return pigstyInfoService.createUpdate()
                .set(PigstyEntity::getAlarmState, AlarmRecordState.warning)
                .where(PigstyEntity::getDeviceId, info.getTargetId())
                .execute()

比如这样的sql

zhou-hao commented 5 months ago

执行频率高不高。完整的调用逻辑大概是咋样的。

MoonBottle commented 5 months ago

执行频率很高(设备一直在上报),完整执行逻辑是设备上报各个属性,存储到设备的子属性表后,监听子属性表的 EntityModifyEvent 或者 EntitySavedEvent 再回写到设备主表的一个字段里做冗余

zhou-hao commented 5 months ago

高频写入,建议使用buffer 批量写入。 可参考 : https://github.com/jetlinks/jetlinks-community/blob/master/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java#L341-L379

MoonBottle commented 5 months ago

高频写入,建议使用buffer 批量写入。 可参考 : https://github.com/jetlinks/jetlinks-community/blob/master/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java#L341-L379

我改下试试,多谢

zhou-hao commented 5 months ago

请教下,怎么以非事务的形式执行sql,也就是某些sql我可以不加锁

截图中的 sql 出现的地方挺多的,但奇怪的是之前的正常的,昨天突然不正常了

可能与并发修改相同数据有关。

MoonBottle commented 5 months ago

高频写入,建议使用buffer 批量写入。 可参考 : https://github.com/jetlinks/jetlinks-community/blob/master/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java#L341-L379

看了下,这个我改动的地方还挺多,有啥办法可以以非事务的形式执行sql么,我想先改了试试,因为数据一直在上报,能接受非事务执行

zhou-hao commented 5 months ago

高频写入,建议使用buffer 批量写入。 可参考 : https://github.com/jetlinks/jetlinks-community/blob/master/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java#L341-L379

看了下,这个我改动的地方还挺多,有啥办法可以以非事务的形式执行sql么,我想先改了试试,因为数据一直在上报,能接受非事务执行

注解@Transactional 或者使用TransactionalOperator手动管理事务。

MoonBottle commented 5 months ago

image

    /**
     * 设备设为告警状态
     */
    @EventListener
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Mono<Integer> triggerAlarm(AlarmHistoryInfo info) {
        String targetType = info.getTargetType();
        // 设备告警
        if (DeviceAlarmTarget.TYPE.equals(targetType)) {
            return pigstyInfoService.createUpdate()
                .set(PigstyEntity::getAlarmState, AlarmRecordState.warning)
                .where(PigstyEntity::getDeviceId, info.getTargetId())
                .execute();
        }
        return Mono.empty();
    }

为啥使用了 @Transactional 注解还是会加锁呢

zhou-hao commented 5 months ago

这和事务没关系吧,还有 deviceId 是否加了索引。

MoonBottle commented 5 months ago

image deviceId 有加索引

zhou-hao commented 5 months ago

其他地方有没有查询操作。

MoonBottle commented 5 months ago

其他地方有没有查询操作。

有查询 pigstyInfo 的操作

MoonBottle commented 5 months ago

其他地方有没有查询操作。

还挺多的,业务都是围绕这张表做的

zhou-hao commented 5 months ago

改成buffer 修改状态试试吧。 参考设备状态同步那个逻辑。

MoonBottle commented 5 months ago

改成buffer 修改状态试试吧。 参考设备状态同步那个逻辑。

MoonBottle commented 5 months ago

解决了,谢谢大佬,是我在设备上报属性的监听里做了太多事,导致长事务了

MoonBottle commented 5 months ago

image 大佬,不好意思再打扰一下,今天生产环境遇到假死问题了,有几个线程的 cpu 一直很高,导致服务无法登录以及别的操作,重启后恢复正常,麻烦有空了帮忙看一下,不着急 这是相关日志:server.log

zhou-hao commented 5 months ago

jetlinks-core版本是最新1.2.2么。 看一下jstack -l结果

MoonBottle commented 5 months ago

jetlinks-core版本是最新1.2.2么。 看一下jstack -l结果

是最新的 1.2.2 ,已经重启了,下次再遇到我 jstack -l 一下

image

MoonBottle commented 4 months ago

大佬,今天又遇到了,这是 jstack -l 的日志: jstack.log

MoonBottle commented 4 months ago

有部分设备使用的是 pythonpaho.mqtt 库,调用了 loop_start()

然后观察日志发现很多日志 log.info("device [{}] session [{}] changed to [{}]", old.getDeviceId(), old, newSession);

image

debug 了下,发现也会走到 jstack 日志里面的 AbstractDeviceSessionManager.java:592 ,不知道是不是这个影响了

zhou-hao commented 4 months ago

一个设备会重复创建mqtt连接?

zhou-hao commented 4 months ago

一个设备只允许一个连接,如果有多个连接,会断掉之前的连接。

MoonBottle commented 4 months ago

一个设备会重复创建mqtt连接?

早上研究了下,生产环境应该不是这个原因,没有相关的这些重复连接的日志

MoonBottle commented 4 months ago

jstack-0412.log jstack-041202.log jstack-041203.log jstack-041204.log jstack-041205.log

大佬,昨晚又出现了,我 jstack -l 了上面这些日志,有空的话,麻烦帮忙分析下? 感谢!

zhou-hao commented 4 months ago

cpu 内存占用高么? 看上去是在接受消息后应答是有死锁?

是最新的代码么 ,对比一下这里。

https://github.com/jetlinks/jetlinks-community/blob/b77cdcb606685bb8f9c92bffe3b4e814bef8a3b8/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/gateway/device/MqttServerDeviceGateway.java#L291

MoonBottle commented 4 months ago

cpu 内存占用高么? 看上去是在接受消息后应答是有死锁?

是最新的代码么 ,对比一下这里。

https://github.com/jetlinks/jetlinks-community/blob/b77cdcb606685bb8f9c92bffe3b4e814bef8a3b8/jetlinks-components/network-component/mqtt-component/src/main/java/org/jetlinks/community/network/mqtt/gateway/device/MqttServerDeviceGateway.java#L291

CPU 占满了,我来对比下代码