文章目录

测试方法的研究

如前文所述,我们需要测试测试心跳故障和连接故障下的TIBCO表现。

经过测试可以发现:

1、 无论在主服务器的TIBCO控制台输入shutdown,还是在Linux命令行下使用kill -9杀TIBCO进程,主服务器均向客户端发送了FIN,ACK,友好的关闭连接,同时也向备份服务器发送了FIN,ACK,备份服务器和客户端均可判断出连接故障,备份服务器开始做主备切换,客户端向备份服务器发送SYN,创建新的连接。

图1 客户端向备份服务器发送SYN,创建新的连接

这两种操作方式均满足连接故障的要求。

2、 直接重启主务器,TIBCO日志显示:

Missing heartbeats from primary server ‘tcp://192.168.65.121:7222’.
Server activating on failure of ‘tcp://192.168.65.121:7222’.
Server rereading configuration.
Recovering state, please wait.
ERROR: Unable to open store file ‘/mqdata/QA/QAEmsServer1/datastore/async-msgs.db’, file may be locked.
ERROR: Unable to open store file ‘/mqdata/QA/QAEmsServer1/datastore/meta.db’, file may be locked.
ERROR: Unable to open store file ‘/mqdata/QA/QAEmsServer1/datastore/sync-msgs.db’, file may be locked.
ERROR: Server failed to recover state.
Server is re-entering standby mode.
Missing heartbeats from primary server

可以清楚的发现,备份服务器检测到心跳异常,并作恢复尝试。

客户端连接的TCP消息,可以看出主服务器未发送FIN,ACK来优雅的关闭连接,客户端数次重传失败后,转而连接备份服务器。

图2 客户端数次重传失败后,转而连接备份服务器

但是需要注意的是:主服务器重启完毕并挂载nfs前,datastore一直处于被锁状态,无法完成主备切换,生产或类生产环境是否存在同样的问题,值得关注。

重启服务器可以满足心跳故障的测试需求。

测试结果

测试环境

TIBCO 服务器 version: 7.0.1 V4
客户端TICBOJAR包:tibjms-6.0.1.jar

心跳故障下的测试

在心跳故障情况下,客户端连接到备份服务器上,由于主备切换未完成,客户端收到Server in standby mode err,然后尝试重连主服务器,往复4次后,客户端抛出异常:CONNECTION EXCEPTION: Connection has been terminated。

图3 由于主备切换未完成,客户端收到Server in standby mode err,然后尝试重连主服务器

连接故障下的测试

Kill 主服务器TIBCO进程后,客户端跟主服务器Say goodbye后,转后连接备份服务器。
比较有意思的是,在客户端向服务端发送一个12字节的流(77 99 aa dd 00 00 00 00 00 00 00 00),并收到确认应答后,交互进入阻塞状态,直到备份服务器完成主备切换。

图4 TIBCO的握手协议

主备切换完毕后,客户端可继续交互,整个过程,客户端未抛出任何异常。
分析tibjms,可以发现,客户端发送的这个字节流,是客户端与服务端的握手协议的一部分,是客户端发送给服务端的一个固定标识。由于客户端采用readFully方式获取服务端的返回应答,因此会长时间阻塞,直到服务端返回12字节的应答码。

如果我们配置了reconnectAttemptTimeout,则这个过程变的可控,在设置的时间内未完成整个握手,则客户端主动发送FIN,ACK,关闭与服务端的连接,往复4次后,备份服务器未完成主备切换,客户端抛出异常。

综述

综上所述:TIBCO已具备较强的容错机制,但是,一旦超出它的控制范围,就需要客户端框架做必要的异常捕获和重连保护,为了测试客户端框架的容错机制,我们可以通过必要的配置,让过程超过TICBO容错范围。

tibjms.jar中的ConnectionFactory的实现与异常的关系

Tibjms.jar中,TibjmsConnectionFactory实现JMS的ConnectionFactory,createConnection方法创建具体的Connection(TibjmsXATopicConnection、TibjmsTopicConnection、TibjmsXAQueue
Connection、TibjmsQueueConnection)并返回。实现类均在构造方法中调用父类TibjmsConnection的构造方法创建TibjmsxLink,并调用 TibjmsxLink.connect创建socket连接和执行握手。
因此只要每次出现异常后调用ConnectionFactory.createConnection即可得到一个新的连接。

文章目录