最近,在 TDengine 的开源社区上我们遇到了两位集群用户,他们都提到了TDengine客户端高可用的问题:
 
用户共同的疑问说明了这个问题是很有代表性的,所以我们精选出来,希望可以从用户的角度对产品的优化形成更多的思考。
 
我们将这个问题细化一下就是「在 TDengine 客户端使用 taos -h FQDN -P port 连接集群的过程中,如果客户端所在节点出现了宕机,本次连接是不是就会以失败而告终呢?」
 
答案显然是「是的」。
 
一位用户和我们表示:TDengine服务端的高可用都做好了,客户端的高可用却没有跟上,实在是太可惜了。
 
事实上,连接失败不假。但其实 TDengine 并不鼓励用户使用如上的方式连接集群 。为什么这么说呢,我们来给大家仔细梳理一下。
 
假设一个用户在连接 TDengine 集群时,他所连接的节点挂掉了。在这一刻,我们会需要两种高可用:一是来自服务端,二是来自客户端。
 
服务端的高可用,指的是当 TDengine 的节点发生故障且超出规定时间无响应时,集群立刻产生系统报警信息并踢掉损坏节点,同时触发自动的负载均衡,系统自动把该数据节点上的数据转移到其他数据节点。
 
而客户端的高可用,指的是 TDengine 在连接失败时立即指定其他可用的数据库服务端供客户端继续连接。
 
重点来了,TDengine 能实现这样的功能吗? 当然可以 
 
下面就是我们并不建议大家在 url 或者 taos 等连接方式中指定 FQDN,而是使用客户端配置文件 taos.cfg 去连接集群的真正原因。后者,客户端会自动连接我们配置好的参数 firstEP 节点,如果在连接瞬间这个节点挂掉了,则会继续连接参数 secondEP 所代表的节点。
 
值得注意的是,只要这两个节点有一个连接成功,客户端的使用就已经没有问题了。因为 firstEP 和 secondEP 只在连接的瞬间会被使用,它提供的并不是完整服务列表,而是连接目标。只要在这短暂的零点几秒内集群连接成功,该节点就会自动获取管理节点的地址信息。而只在连接的这一瞬间,两个节点同时宕机掉的可能性是极低的。后续,即使 firstEP 和 secondEP 两个节点全都坏掉,只要集群可以对外服务的基本规则没有被打破,就仍然可以正常使用。这就是 TDengine 维护客户端高可用的方法。
 
当然,维护客户端高可用的方法不只这一个。这两位用户均使用了 load balance 在外层包裹一层负载均衡。在这个过程中,两个人又各自遇到了同样的问题。原来他们在做四层网络负载的时候,都只使用了 TCP 端口,连接都失败了。于是,GitHub 上才有了他们共同的疑问—— TDengine 到底是如何实现客户端的高可用的 
 
下面我们分析一下,他们为什么在做网络负载均衡时还是会出现连接失败的问题。
 
TDengine 的官方文档上有一段内容可以解释上面的情况:考虑到物联网场景下,数据写入的包一般不大,因此除支持 TCP 连接之外,RPC 还支持 UDP 连接。当数据包小于 15KB 时,RPC 将采用 UDP 方式进行连接,否则将采用 TCP 连接。超过 15KB 的,或者是查询类的操作,采取 TCP 的方式进行传输。
 
这就是答案了,建立连接的数据包小于 15KB,走的是 UDP 的连接。
 
所以,当他们都加上 UDP 的转发规则之后都成功完成了集群外围的网络负载均衡。这样搭建的好处,除了可以同样完成客户端的高可用以外,还会使“开发”与“运维”的场景更加清晰,更加便于管理。
 
有趣的是,第一位解决问题的 yakir-Yang 在发现了另外一个问题后还对第二位提问者 stringhuang 做了热心的解答。因为他刚刚经历过一模一样的问题,一眼就看到了另一位提问者的痛点。
 
于是互不认知的三方,便在这个开源社区里进行了一次和谐的技术互动。最终的结果是:提问者们在了解了 TDengine 的机制后,也成功地在这个新产品上搭建起了自己熟悉的高可用策略。