2017-05-15 49 views
0

我正在将使用JGroups 3.6.6的应用程序迁移到JGroups 4.0.2。 JGroups 3.6.6中的'Address'类型是可序列化的,但由于安全原因,它已在JGroups 4.0.2中进行了Streamable。由于这个原因,我在国家转移期间遇到了问题。这是我用来进行国家转移的班级。JGroups状态转移地址键映射

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. 有没有一种方法来实现Streamable为用户定义的单身人士类?这种情况下的'状态'对象是单例。

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

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

在单例中调用newInstance会导致异常。这是我在我的问题中试图传达的“是否有一种方法可以为用户定义的Streamable实现singleton class?”。

在构造replyFromBuffer方法(可在RequestCorrelator中找到)和setState方法中内部调用Util.objectFromStream方法。虽然我避免在setState方法中调用objectFromStream,但来自RequestCorrelator的内部调用仍然存在问题。

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

编辑3: 请参阅Bela Ban的答案和下面的解决方案的评论。

回答

1

我会通过首先将条目数量编组为一个int来实现封送哈希映射,然后迭代条目并分别编组每个Address,ScaleInfo条目。

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

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

回复单身:我不明白这是怎么从一个编组非单不同...

+0

我已经加入和解组的地图有问题,它工作正常。但是,这只是一个解决方法,因为我在应用程序中具有功能。一个更严重的问题是该实例是单例。我更新了这个问题,解释了因使用Streamable Singleton而面临的问题。 – kishore

+0

截至目前,我已经避免发送“状态”,并修改了在调用者封送之后发送字节缓冲区的代码。然后被调用者执行非编组(事先知道该类是单例)。这对我很好。我想知道这是否是正确的做法。 – kishore

+0

发送一个字节缓冲区总是有效的,也许是像你这样的单身人士的最佳解决方案。 –