我在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
的系统咨询消息。但是,我不知道正确的方式来收听此消息,也不会在收到消息时尝试恢复。
答案 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()
如何测试断开连接并重新连接事件:
$ tibrvlisten -service 8800 -daemon tcp:8800 TEST.MESSAGE
$ tibrvsend -service 8800 -daemon ${tibrvlisten.hostname}:8800 TEST.MESSAGE hello
tibrvlisten
应记录:subject=TEST.MESSAGE, message={DATA="hello"}
new TibrvRvdTransport("8800", null, "${tibrvlisten.hostname}:8800")
tibrvlisten
,然后终止后台进程rvd
,例如$ ps -efjww | egrep 'rvd +-listen' | awk '{print $2}' | xargs kill
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
tibrvlisten
并等待Java后台线程自动重新连接。