页面树结构
转至元数据结尾
转至元数据起始

(本文档仅供参考)

问题描述

数据模型设置抽取后,发现sql语句复杂及数据量大的抽取,会导致模型抽取一直处于运行状态,没有任何报错,查看sql日志,发现sql一直在运行,数据库方面查询sql已经完成,smartbi并未收到任何中断或者报错等信息,导致一直在运行状态等待数据返回。

原因分析

经过排查发现在防火墙上有设置TCP超时时间30分钟,一旦超过30分钟TCP无任何活动,就会断开TCP连接,并且不会给两边任何通知,导致两边还在运行,smartbi未接受到返回值或者断开报错,就会一直处于运行状态。

具体可以参考:https://zhuanlan.zhihu.com/p/670111809?utm_id=0

解决方案

1、调大防火墙的连接切断时长
这是一个临时解决方法,比如将防火墙的连接超时时间调整为8小时,这样可以尽量避免空闲连接的切断,但无法完全避免,因为无法预计连接会被空闲多久,如果你的系统不是总有人访问的话,那么连接迟早会因为空闲而被切断,导致一些不可预计的问题,而调大超时时间只是缓解而已


2、tcp keepalive功能
tcp的keepalive,其实就是用来保持tcp连接的,其原理简单说就是如果一个TCP连接在指定的时间内没有任何活动,会发送一个探测包到连接的对端,检测连接的对端是否仍然存在,如果对端一定时间内仍没有对探测的响应,会再次发送探测包,发送几次后,仍然没有响应,就认为连接已经失效,关闭本地连接。
tcp keepalive并不是默认开启的,在开发程序时可以设置tcp keepalive为true,这样tcp连接在一定时间内没有任何数据报文传输则启动探测,这个时间一般是操作系统规定,Linux系统中可以通过设置net.ipv4.tcp_keepalive_time来修改,默认是7200秒,即2小时。当然在编程时也可以设置这个时间用于当前socket,但是Java的Socket API中好像只有设置keepalive=true,并没法设置tcp_keepalive_time
当设置了tcp keepalive之后,只要tcp探测包发送的时间小于防火墙的连接超时时间,防火墙就会检查到连接中仍然有数据传输,就不会断开这个连接。
使用JDBC创建的数据库tcp连接是没有设置keepalive的,这点可以通过Linux的netstat或ss命令在数据库客户端(即应用端)验证
使用命令netstat -ano 或 ss -ano,其中参数o都是显示timer计时器,timer计时器在连接建立状态下可以对连接保活计时
netstat命令对没有开启keepalive的tcp连接显示为:off (0.00/0/0)
ss命令对没有keepalive的tcp连接,不会显示timer计时器

3、Oracle数据库的DCD
Oracle提供了类似tcp keepalive的机制,也就是DCD(Dead Conneciton Detection)。在$ORACLE_HOME/network/admin/sqlnet.ora文件中增加如下一行:
sqlnet.expire_time=NNN
这里NNN为分钟数,Oracle数据库会在会话IDLE时间超过这个指定的时间时,检测这个会话的对端(即客户端)是否还有效。避免客户端由于异常退出,导致会话一直存在。
同样的如果DCD的时间比防火墙切断空闲连接的时间短,连接也可以一直保持

  • 无标签