简体   繁体   中英

How to catch Tibrv RVD.DISCONNECTED message in Java?

I have a long running Tibrv connection from a Java process.

I was surprised to see this log entry today (printed on stderr):

2018-02-01 08:15:44 RV: TIB/Rendezvous Error Not Handled by Process: {ADV_CLASS="WARN" ADV_SOURCE="SYSTEM" ADV_NAME="RVD.DISCONNECTED"}

What is the right way to catch this error and reconnect?

My process needs to be fault tolerant. (I think the server on the other side was rebooted.)

Sample connection code:

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

According to the official Tibrv docs (p282), there is a System Advisory Message called _RV.WARN.SYSTEM.RVD.DISCONNECTED . However, I don't know the correct way to listen for this message, nor attempt recovery upon receipt.

This took me a while to figure out, so I am answering my own question.

In short, the Tibrv Java library uses a private thread to automatically monitor for disconnect and re-connect. The purpose of 'user-space' monitoring is to provide gracefully handling of these events (fault tolerance, etc.).

The technical solution is to listen for two special RVD messages:

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

A single TibrvListener with subject wildcard can be used.

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()

How to test disconnect and re-connect events:

  1. Create a Tibrv listener from command line:
    • $ tibrvlisten -service 8800 -daemon tcp:8800 TEST.MESSAGE
  2. Send a test message from command line:
    • $ tibrvsend -service 8800 -daemon ${tibrvlisten.hostname}:8800 TEST.MESSAGE hello
    • tibrvlisten should log: subject=TEST.MESSAGE, message={DATA="hello"}
  3. In Java, connect to the Tibrv listener: new TibrvRvdTransport("8800", null, "${tibrvlisten.hostname}:8800")
  4. Stop tibrvlisten with Ctrl+C, then kill background process rvd , eg, $ ps -efjww | egrep 'rvd +-listen' | awk '{print $2}' | xargs kill $ ps -efjww | egrep 'rvd +-listen' | awk '{print $2}' | xargs kill
  5. In Java, upon receiving disconnect event, immediately send message:
    • final TibrvMsg m = new TibrvMsg(); m.setSendSubject("TEST.MESSAGE"); m.add("DATA", "hello"); tibrvRvdTransport.send(m);
    • send() will fail with TibrvException : error=21, message="Could not connect to daemon"
    • Public field int TibrvException.error values can be found here: TibrvStatus , eg, DAEMON_NOT_CONNECTED = 21
  6. Restart tibrvlisten and wait for Java background thread to automatically re-connect.
  7. In Java, upon receiving re-connect event, messages may again be sent without error.

Credit for tibrvlisten

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM