[英]How do I force JGroups which node to make coordinator?
我正在寻找一种方法来强制JGroups使用特定的服务器作为协调器,如果该服务器不存在,请选择一个新的协调器,直到指定的一个重新加入集群并接替其担任协调器为止。
在这种情况下,我们有一些信息是由协调员通过侦听某个主题以获取更新来推送到群集中的,但是获取和处理这些更新可能会占用大量资源,因此我们不希望它将任何东西存储到外界。 因此,在集群前面的负载均衡器中,我们将其设置为不发送给协调器。 但是由于协调器是随机选举的,因此我们基本上需要关闭集群,直到只有一台机器在其中,然后再启动其余集群。
当前尚无办法。 Jgroups已花费大量时间来确保协调器可以是组中的任何节点。 维护和监视组成员资格列表的运行状况的所有任务在组中的所有成员之间共享,以确保协调员的职责不会对协调员的绩效产生太大影响。 标准的GMS(Group MembershipService)协议栈类负责协调器的选择。 当前,它只是视图列表中的第一台主机。
要获得此行为,您将必须实现自己的协议栈。 有趣的是,我一直在为Jgroups开发协议栈,该协议栈大致实现了您所要的内容,但是还没有准备就绪。
其他人可能对此问题不屑一顾。 我建议在jgroups邮件列表上发布并询问相同的问题。
刚刚偶然发现了这篇文章。 在JGroups中有一种简单而标准的方法可以做到这一点:[1]。 从本质上讲,我们让用户代码控制视图的生成。
[1] http://www.jgroups.org/manual4/index.html#MembershipChangePolicy
您可以将所需的节点设置为协调器。 : github样本
我为所有节点上完成的更改和完整的代码添加了同步块:
public static final String GMS_DELTA_VIEW_FIELD_NAME = "use_delta_views";
/**
* Change coordinator to {@code desiredCoordinator}. Must be invoked from coordinator.
* @param desiredCoordinator
* @return {@code true} if changes success, {@code false} overwise
*/
boolean changeCoordinator(JChannel currentChannel, Address desiredCoordinator) {
if(!Util.isCoordinator(currentChannel.getAddress)) {
throw new RuntimeException("The current node is not coordinator.");
}
ArrayList<Address> newMembersOrder = Lists.newArrayList(currentView.getMembers());
// Switch desired node to first place
Collections.swap(newMembersOrder, 0, newMembersOrder.indexOf(desiredCoordinator));
// Create new view
long newId = currentView.getViewId().getId() + 1;
View newView = new View(newMembersOrder.get(0), newId, newMembersOrder);
GMS gms = (GMS)clusterChannel.getProtocolStack().findProtocol(GMS.class);
CustomProtocol protocol = new CustomProtocol(newMembersOrder.stream()
.filter(item -> !item.equals(currentChannel.getAddress()))
.collect(Collectors.toSet()));
boolean oldUseDeltaViews = (Boolean)gms.getValue(GMS_DELTA_VIEW_FIELD_NAME);
try {
// Disable using_delta_views at GMS
gms.setValue(GMS_DELTA_VIEW_FIELD_NAME, false);
// Insert custom protocol below GMS for synchronizing with VIEW_ACK events
currentChannel.getProtocolStack().insertProtocolInStack(protocol, gms, ProtocolStack.BELOW);
gms.castViewChange(newView, null, newMembersOrder);
// Wait no more than 30 seconds to all VIEW_ACK responses
if (!protocol.collector.waitForAllAcks(TimeUnit.SECONDS.toMillis(30))) {
return false;
}
return true;
}
finally {
// Repair old state
gms.setValue(GMS_DELTA_VIEW_FIELD_NAME, oldUseDeltaViews);
currentChannel.getProtocolStack().removeProtocol(protocol);
}
}
private class CustomProtocol extends Protocol implements UpHandler {
AckCollector collector;
public CustomProtocol(Collection<Address> waitedAddresses) {
collector = new AckCollector(waitedAddresses);
}
@Override
public Object up(Event evt) {
if(evt.getType() == Event.MSG) {
final Message msg=(Message)evt.getArg();
GmsHeader hdr=(GmsHeader)msg.getHeader(proto_id);
if(hdr != null && hdr.getType() == GmsHeader.VIEW_ACK) {
collector.ack(msg.getSrc());
}
}
return super.up(evt);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.