解决 clickhouse jdbc 偶现 failed to respond 问题

背景

Clickhouse集群版本为 Github Clickhouse 22.3.5.5, clickhouse-jdbc 版本为 0.2.4

问题表现

随着业务需求的扩展,基于Clickhouse 需要支持更多任务在期望的时效内完成,于是将业务系统和Clickhouse交互的部分都提交给可动态调整核心参数的线程池去执行,尽量可控的利用Clickhouse集群的计算资源。

然后一测试就出现了高频的异常:ru.yandex.clickhouse.except.ClickHouseUnknownException: ClickHouse exception, code: 1002, host: 192.168.1.1, port: 8123; 192.168.1.1:8123 failed to respond

搜索发现有比较多类似问题


解决经历

首先问题就指向了驱动版本, 社区在0.2.5优化了这个问题, 那就只能升级驱动版本了, 由于这个项目也是接手的,通常来说遇到性能问题,不会第一时间考虑升级依赖版本除非找到确认的依据是版本有缺陷,因为风险不可控.

但是社区还有类似问题反馈,BatchUpdateException during inserts with jdbc driver 于是直接跨多个版本升到了0.6.0

升级后使用线程池跑确实就不会出现高频的报错了,但是仍偶现有1002报错,当时加了重试逻辑,赶业务进度,测试后就上线了,但是遇到了一个不大不小的坑: Druid管理的JDBC Connection 在调用getConnection().getSchema(); 时,0.2.4版本的驱动正常返回了连接所在的数据库名,但是0.6.0返回了null,导致部分业务场景出错了,只好紧急修复了,原因是因为com.clickhouse.jdbc.JdbcConfig#databaseTerm 的值默认是catalog模式,要改成shcema模式才会返回数据库名 jdbc url后追加参数 databaseTerm=schema
在这里插入图片描述

Clickhouse 里对于JDBC 中catalog 和 schema 的实现 都是作为 数据库的别名。

过了一段时间,业务又发生了扩展,要跑的任务更多了,每到高频的跑任务时,就可能会看到告警群会来几条1002的报错告警。然后开始新一轮找问题了. 最终多轮压测调试结论如下。


1. socket_timeout

由于升级驱动到0.6.0时也调整了JDBC的参数, 那时只看到了客户端的值远大于服务端的值,就只想着尽量复用连接少建立连接的开销实际上不是重点,就把驱动的socket_timeout 设置为了和服务端的 tcp_keep_alive_timeout保持一致为 290s,(注意默认值是3s 部署时调整了参数 )。

实际上连接的活跃性和socket_timeout 没有关系,见下文,当长时间执行的DDL和查询会报错 Read timeout http read timeout 30, 因此socket_timeout设置为业务合理值即可。

注意 socket_timeout 的默认值及实现机制均由驱动实现,MySQL PostgreSQL Clickhouse 等均不同,此处Clickhouse 0.6.0 的驱动内 socket_timeout 默认值为30S在这里插入图片描述

2. 连接 keepalive

通过这个PR Validate stale connection to fix the bug: failed to respond 注意到项目内没有设置合理的连接保活机制。

按这个场景来说,当客户端的一个连接到了超时的边界值时,考虑到网络延迟,客户端会认为是有效的,但是服务端认为超时了,就会关闭连接, 就又会抛出1002了,如果SQL的提交是低频的就不容易出现这个情况,当有多个线程并发跑1小时以上时概率就大大增加了,此时需要加入连接的心跳机制规避服务端关闭不活跃连接的情况。

BatchUpdateException during inserts with jdbc driver

在这里插入图片描述依据开发者的建议,我们将心跳检查的周期设置的比tcp_keep_alive_timeout的290更小,例如120s。

例如Druid连接池 通过如下参数开启

      # 心跳保活
      keepAlive: true
      # 心跳保活间隔,keepAlive开启才生效
      keepAliveBetweenTimeMillis: 120000
      # 配置检测连接是否有效 创建连接和心跳保活时执行 检查sql 通常默认是 select 1 或原生支持ping协议包(MySQL Oracle). 
      validationQuery: SELECT 1

两项调整后,目前1002问题尚未出现

  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值