我在以下配置中使用Hazelcast 3.3.3(最新稳定版):2节点群集和1个客户端。 客户端将任务放入IMap,而节点执行它们并在完成后更新相应的映射值。客户通过map.addEntryListener()注册的EntryListener(entryUpdated())获得通知。
当我模拟网络问题时出现问题:" tcpkill -i lo port或port"。停止tcpkill后,群集状态会自动恢复。到现在为止还挺好。 那时有两种方式(有时是1种,有时是2种):
我无法在日志中找到任何可疑内容(log4j.logger.com.hazelcast = debug已启用)。 尝试启用tcpkill的不同间隔:大于和小于cluster.max.no.heartbeat.seconds和cluster.max.no.master.confirmation.seconds。行为是一样的,似乎它们对问题没有影响。
有什么想法吗?
答案 0 :(得分:0)
似乎,我找到了案例2的答案。看起来是 Hazelcast bug 。
我查看了两个版本的源代码: 3.2.5 (我第一次遇到问题的那个)和 3.3.3 。这就是我找到的。
EventServiceImpl 类至少负责存储/提供 EventRegistration -s,订阅包含处理地图更新的订阅。当客户端告诉map.addEntryListener(..)
该侦听器最终作为 EventRegistration 出现在群集 EventServiceImpl 中时。
当群集节点执行某些地图更新 EventServiceImpl 迭代其 EventRegistration -s:
@Override
public void publishEvent(String serviceName, Collection<EventRegistration> registrations,
Object event, int orderKey) {
...
for (EventRegistration registration : registrations) {
...
Registration reg = (Registration) registration;
if (isLocal(reg)) {
executeLocal(serviceName, event, reg, orderKey); // EXECUTION GOES HERE
continue;
}
if (eventData == null) {
eventData = nodeEngine.toData(event);
}
EventPacket eventPacket = new EventPacket(registration.getId(), serviceName, eventData);
sendEventPacket(registration.getSubscriber(), eventPacket, orderKey);
}
}
并通知感兴趣的各方。与客户端订阅相关联的注册包含对 ClientEndpoint 的引用,最终为连接以发送更新。
当群集遇到网络问题时(我使用tcpkill阻止节点之间的通信),其状态发生变化,以便客户端断开连接。 tcpkill停止后,节点成功加入群集 和客户端恢复其连接。在 EventServiceImpl 保持不知道更改的意义上,两个Hazelcast版本都无法识别此重新连接。行为因Hazelcast版本而异: