带有地址键的 Map 的 JGroups 状态传输

JGroups state transfer of a Map with Address keys

我正在将使用 JGroups 3.6.6 的应用程序迁移到 JGroups 4.0.2。 JGroups 3.6.6 中的 'Address' 类型是可序列化的,但出于安全原因,它已在 JGroups 4.0.2 中变为 Streamable。因此,我在状态转移期间遇到了问题。这是我用于状态传输的class。

public class State implements Streamable {
/**
 * 
 */
private static final Logger     log                             = LogManager.getLogger(State.class);
private Map<Address, ScaleInfo> nwMap                       = new ConcurrentHashMap<>();
private Set<Address>            listOfSyncedMastersInCluster    = Collections
                                                                        .newSetFromMap(new ConcurrentHashMap<Address, Boolean>());
private boolean                 hasMasterMajorityInCluster      = false;
private Address prevCoordAddress = null;
private Address currentCoordAddress = null;
private static final State      instance                        = new State();

private State() {

}

public static State getInstance() {
    return instance;
}}

状态传输逻辑,

@Override
public void getState(OutputStream output) throws Exception {
    State state = State.getInstance();
    synchronized (state) {
        Util.objectToStream(state, new DataOutputStream(output));
    }
}

@Override
public void setState(InputStream input) throws Exception {
    State state = State.getInstance();
    synchronized (state) {
        state.setInstance((State) Util.objectFromStream(new DataInputStream(input)));
    }
}

问题是我找不到用地址键编组地图的方法。我尝试调试以查看发生了什么,我可以看到 Map 被视为原始类型并且 JGroups 尝试对其进行序列化。这会导致异常。这是我用来实现 Streamable 的代码,

@Override
public void writeTo(DataOutput out) throws Exception {
    Util.writeObject(networkMap, out);
    Util.writeAddresses(listOfSyncedMastersInCluster, out);
    out.writeBoolean(hasMasterMajorityInCluster);
    Util.writeAddress(prevCoordAddress, out);
    Util.writeAddress(currentCoordAddress, out);
    out.writeUTF(Util.objectToByteBuffer(this).toString());
}
@Override
public void readFrom(DataInput in) throws Exception {
    nwMap = (Map<Address, ScaleInfo>) Util.readObject(in);
    listOfSyncedMastersInCluster = (Set<Address>) Util.readObject(in);
    hasMasterMajorityInCluster = in.readBoolean();
    prevCoordAddress = Util.readAddress(in);
    currentCoordAddress = Util.readAddress(in);
    instance = Util.objectFromByteBuffer(in.readUTF().getBytes());
}
  1. 有没有办法编组 'nwMap' 成员变量?
  2. 有没有办法为用户定义的 单例 class 实现 Streamable? 'State' 本例中的对象是单例。

编辑 1: 第二个问题强调单例class的情况。调用内部调用 Util.readGenericStreamable 方法的 Util.objectFromStream 方法时会发生问题。在此方法中,将执行以下代码块。

    {
        String classname=in.readUTF();
        clazz=ClassConfigurator.get(classname, loader);
        retval=(T)clazz.newInstance();
    }

在单例上调用 newInstance 导致异常。这就是我在问题“是否有办法为用户定义的 singleton class? 实现 Streamable 的方法” .

Util.objectFromStream 方法在构建 replyFromBuffer 方法(在 RequestCorrelator 中找到)和 setState 方法时在内部调用。尽管我避免在 setState 方法中调用 objectFromStream,但来自 RequestCorrelator 的内部调用仍然会导致问题。

编辑 2: 更新了第二个问题。

编辑 3: 参考Bela Ban的回答和下面的评论来解决。

我将通过首先将条目数编组为 int,然后遍历条目并分别编组每个 Address,ScaleInfo 条目来实现编组哈希图。

Util 中有方法,例如 writeAddress()writeAddresses() 编组地址或地址列表。

在接收方,读取int N并创建一个hashmap,然后读取N个条目。 Util.readAddress() 可用于从 byte[] 数组/输入流创建地址。

关于单例:我看不出这与编组非单例有何不同...