问题背景
客户的查询语句是通过一个调度程序走 ODBC 连上 OushuDB 执行。但是在客户环境下,对于执行时间较长(比如要跑 40+min)的查询,调度程序会长时间 hang 住,并在最终都无法收到执行结果;而短时查询工作一切正常。
问题排查
- 首先检查是否 QD 异常退出:在筛过 OushuDB master 的日志后,没有发现异常信息。重跑之后发现 QD 是正常执行结束后退出的。
- 再检查网络环境:重跑期间,在 QD 侧抓包:
tcpdump -nnSX -i ${eth} port ${master_port}
,发现在返回执行结果时,一直不能收到客户端的 ack,多次重发之后,qd 认为连接失效并自动退出
问题分析
客户端和 DB 建连后通信正常,但在长时间 idle 后通信失败。这种现象首先会考虑是不是操作系统网络相关配置有问题。但在检查客户端和 QD 的操作系统配置后: sysctl -a | grep tcp
没有发现问题。最后猜测是客户环境的网络连接有相关限制,但不清除是中转的路由或者相关的防火墙配置,会把这种长时间不通信的连接认为无效而拒绝继续收发包。
问题解决
OushuDB 提供了 3 个参数用于控制连接的 keepalive 属性:tcp_keepalives_idle
, tcp_keepalives_interval
, tcp_keepalives_count
。为了绕过客户环境的限制,我们可以把 keepalive 的触发时间调短:set tcp_keepalives_idle to 180; set tcp_keepalives_interval to 10;
,然后问题解决,这也验证了我们的猜测是对的。