关于jdbc:如何解决JDBC死链接导致NIFI线程假死

42次阅读

共计 1320 个字符,预计需要花费 4 分钟才能阅读完成。

景象

ExcuteSql 不工作不调度,stop 也进行不了,active 的工作个数也不升高。

场景复现

1、模拟现场结构数据

2、Tc 命令模仿现场网络环境模拟丢包 30%

tc qdisc del dev enp4s0f0 root netem loss 30%

问题排查

netstat -pan | grep $NIFI_PID

能够看到和数据库开启了 5 个 tcp 连贯,也能够看到有五个 socket 处于连贯状态

间接看线程

jstack -l $NIFI_PID | grep ‘java.net.SocketInputStream.socketRead0(Native Method)’ -C 10

察看了一段时间,socket 依然没有敞开,能够根本必定现场环境应该曾经复现。

问题剖析

一次残缺的数据库申请包含三个阶段:

1、建设连贯

2、数据传输

3、断开连接 connect timeout: 如果与服务器 (这里指数据库) 申请建设连贯的工夫超过 ConnectionTimeOut,就会抛 ConnectionTimeOutException,即服务器连贯超时,没有在规定的工夫内建设连贯。

socket timeout: 如果与服务器连贯胜利,就开始数据传输了。如果服务器解决数据用时过长,超过了 SocketTimeOut,就会抛出 SocketTimeOutExceptin,即服务器响应超时,服务器没有在规定的工夫内返回给客户端数据。

在未设置超时工夫场景下,nifi 通过 jdbc 获取数据库数据,实质是操作系统在调用 Socket.read(),如果网络问题被阻塞住,那么操作系统会很少在调用 Socket,java 培训因为底层没有数据交互,那么其无奈晓得对端是否宕机,所以会始终期待。

难道零碎没有默认的 socketTimeout?

有的,上述场景下内核会在一个 socket 两个小时都没有数据交互状况下 (可设置) 启动 keepalive 定时器来探测对端的 socket。

也就是说呈现假死会在 7875 秒后复原,大略两个多小时吧。

这就是 nifi 端线程假死的起因;

论断

JDBC 的 socket 未设置超时,呈现了死连贯。

JDBC 驱动是用 Socket 形式与数据库连贯的,应用程序和数据库之间的连贯超时并不是由数据库解决的。

当数据库忽然宕掉或产生网络谬误(设施故障等)时,JDBC 驱动的 Socket 超时的值是必须的。因为 TCP/IP 的构造,Socket 没有方法检测到网络谬误,因而利用不能检测到与数据库到连贯断开了。如果没有设置 Socket 超时,应用程序会始终期待数据库返回后果。(这个连贯也被叫做“死连贯”)为了防止死连贯,Socket 必须要设置超时工夫。Socket 超时能够通过 JDBC 驱动程序配置。通过设置 Socket 超时,能够防止出现网络谬误时始终期待的状况并缩短故障工夫。
在 timeout 为 0 的时候,走默认的零碎调用不设置超时工夫的逻辑。在 timeout>0 时,将 socket 设置为非阻塞,而后用 select 零碎调用去模仿超时, 而没有走 linux 自身的超时逻辑。

解决措施

设置 socket 和 Connection 的超时工夫。

避免因为网络问题呈现死连贯,给数据库的拜访 url 加 socket timeout 和 Connection timeout。

正文完
 0