如何在Java中捕获Tibrv RVD.DISCONNECTED消息?

时间:2018-02-01 13:13:48

标签: java tibco

我在Java进程中有一个长期运行的Tibrv连接。

我很惊讶今天看到这个日志条目(打印在stderr上):

  

2018-02-01 08:15:44 RV:进程未处理TIB / Rendezvous错误:   {ADV_CLASS =" WARN" ADV_SOURCE =" SYSTEM" ADV_NAME =" RVD.DISCONNECTED"}

捕获此错误并重新连接的正确方法是什么?

我的流程需要具备容错能力。 (我认为另一侧的服务器已重新启动。)

示例连接代码:

Tibrv.open(Tibrv.IMPL_NATIVE);
final TibrvRvdTransport tibrvRvdTransport =
    new TibrvRvdTransport(tibrvService, nullableTibrvNetwork, tibrvDaemon);

根据official Tibrv docs(p282),有一个名为_RV.WARN.SYSTEM.RVD.DISCONNECTED系统咨询消息。但是,我不知道正确的方式来收听此消息,也不会在收到消息时尝试恢复。

1 个答案:

答案 0 :(得分:0)

我花了一些时间才弄明白,所以我回答了自己的问题。

简而言之,Tibrv Java库使用专用线程来自动监视断开连接和重新连接。用户空间的目的'监控是为了优雅地处理这些事件(容错等)。

技术解决方案是收听两条特殊的RVD消息:

  • _RV.WARN.SYSTEM.RVD.DISCONNECTED
  • _RV.INFO.SYSTEM.RVD.CONNECTED

可以使用带主题通配符的单个TibrvListener

final String subjectWildcard = "_RV.*.SYSTEM.RVD.*";
final Object nullableClosure = null;
new TibrvListener(
    Tibrv.defaultQueue(),
    // @NotThreadSafe
    new TibrvMsgCallback() {
        @Override
        public void onMsg(TibrvListener tibrvListener, TibrvMsg tibrvMsg) {
            final String sendSubject = tibrvMsg.getSendSubject();
            if ("_RV.WARN.SYSTEM.RVD.DISCONNECTED".equals(sendSubject)) {
                // TODO
            }
            else if ("_RV.INFO.SYSTEM.RVD.CONNECTED".equals(sendSubject)) {
                // TODO
            }
        }
    },
    tibrvRvdTransport, subjectWildcard, nullableClosure);

// Next: Setup a daemon thread to dispatch incoming Tibrv messages.
{
    final Thread thread = new Thread(() -> {
        final TibrvQueue tibrvQueue = Tibrv.defaultQueue();
        while (true) {
            try {
                tibrvQueue.dispatch();
            }
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    });
    thread.setDaemon(true);
    thread.start();
}

Credit for TibrvListener and TibrvQueue.dispatch()

如何测试断开连接并重新连接事件:

  1. 从命令行创建Tibrv侦听器:
    • $ tibrvlisten -service 8800 -daemon tcp:8800 TEST.MESSAGE
  2. 从命令行发送测试消息:
    • $ tibrvsend -service 8800 -daemon ${tibrvlisten.hostname}:8800 TEST.MESSAGE hello
    • tibrvlisten应记录:subject=TEST.MESSAGE, message={DATA="hello"}
  3. 在Java中,连接到Tibrv侦听器:new TibrvRvdTransport("8800", null, "${tibrvlisten.hostname}:8800")
  4. 使用Ctrl + C停止tibrvlisten,然后终止后台进程rvd,例如$ ps -efjww | egrep 'rvd +-listen' | awk '{print $2}' | xargs kill
  5. 在Java中,收到disconnect事件后,立即发送消息:
    • final TibrvMsg m = new TibrvMsg(); m.setSendSubject("TEST.MESSAGE"); m.add("DATA", "hello"); tibrvRvdTransport.send(m);
    • send()将因TibrvException而失败: error = 21,message ="无法连接到守护进程"
    • 公共字段int TibrvException.error值可在此处找到: TibrvStatus,例如DAEMON_NOT_CONNECTED = 21
  6. 重新启动tibrvlisten并等待Java后台线程自动重新连接。
  7. 在Java中,收到重新连接事件后,可能会再次发送消息而不会出错。
  8. Credit for tibrvlisten