带有地址键的 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());
}
- 有没有办法编组 'nwMap' 成员变量?
- 有没有办法为用户定义的 单例 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[] 数组/输入流创建地址。
关于单例:我看不出这与编组非单例有何不同...
我正在将使用 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());
}
- 有没有办法编组 'nwMap' 成员变量?
- 有没有办法为用户定义的 单例 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[] 数组/输入流创建地址。
关于单例:我看不出这与编组非单例有何不同...