4、障栅同步
进入BSPPeerImpl.sync()方法中,sync()方法主要实现的方法是:messenger.getOutgoingBundles()、messenger.transfer()、enterBarrier()、messenger.clearOutgoingMessages()、leaveBarrier()等方法,
BSPPeerImpl.sync()代码为:
public final void sync() throws IOException, SyncException,
InterruptedException {
// normally all messages should been send now, finalizing the send phase
Iterator<Entry<InetSocketAddress, BSPMessageBundle<M>>> it;
it = messenger.getOutgoingBundles();
while (it.hasNext()) {
Entry<InetSocketAddress, BSPMessageBundle<M>> entry = it.next();
final InetSocketAddress addr = entry.getKey();
final BSPMessageBundle<M> bundle = entry.getValue();
// remove this message during runtime to save a bit of memory
it.remove();
try {
messenger.transfer(addr, bundle);
} catch (Exception e) {
LOG.error("Error while sending messages", e);
}
}
if (this.faultToleranceService != null) {
try {
this.faultToleranceService.beforeBarrier();
} catch (Exception e) {
throw new IOException(e);
}
}
long startBarrier = System.currentTimeMillis();
enterBarrier();
if (this.faultToleranceService != null) {
try {
this.faultToleranceService.duringBarrier();
} catch (Exception e) {
throw new IOException(e);
}
}
// Clear outgoing queues.
messenger.clearOutgoingMessages();
leaveBarrier();
incrementCounter(PeerCounter.TIME_IN_SYNC_MS,
(System.currentTimeMillis() - startBarrier));
incrementCounter(PeerCounter.SUPERSTEP_SUM, 1L);
currentTaskStatus.setCounters(counters);
if (this.faultToleranceService != null) {
try {
this.faultToleranceService.afterBarrier();
} catch (Exception e) {
throw new IOException(e);
}
}
umbilical.statusUpdate(taskId, currentTaskStatus);
}
从it = messenger.getOutgoingBundles()和由normally all message should been send now,finalizing the send phase可以看出:当job运行到sync()的时候所有的信息才开始进行传递。当信息传递给BSPMessageBundle后原先在内存中的信息被删除以节省内存空间。
在障栅同步阶段有个很重要的步骤-转换
追踪到mapMessages.add(GraphJobMessage item)方法得到类ConcurrentLinkedQueue.add()中的ConcurrentLinkedQue.offer(Ee)方法(类ConcurrentLinkedQueue extends AbstractQueue implemments Queue)
其中MANAGER_MAP是ConcurrentHashMap的对象,localQueueForNextIteraton是SychronizedQueue(extends MessageQueue)对象。有MANAGER_MAP.get(addr).local qQueueNextIteration.addBundle(bundle)可以看出把hashMap的通信信息转换为 Queue(队列)进行传送,因此可以看出,通信信息的传输其实是用Queue(队列)数据格式进行传输的。
信息传输结束后,相应的信息会到障栅同步后才能参加运算,在BSPPeerImpl.sync()方法中进实现方法enterBarrier(),进入enterBarrier()方法
所以,顶点间的信息通信是通过BSPPeerImpl.sync()中的clearOutgoingMessage()方法进行通信发送传输的。
5、信息接收在类GraphJobRunner中的loadVertices()方法中运行peer.send(Entry.getKey(),GraphJobMessage)、peer.sync()、peer.getCurrentMessage()等方法实现通信信息的发送和传输,接下来要解析peer.getCurrentMessage(),getCurrentMessage()解释为:return a received message
由localQueue.poll()得出,信息的接收也是通过Queue来完成的。
在GraphJobRunner.loadVertices()方法完成了信息的发送(send())、传递、障栅同步(sync())、接收(getCurrentMessage())等操作,而且信息的真正发送是在障栅同步(sync())阶段开始的。信息的发送和接收并不是一一对应的。
每个bsp任务信息传递都是一组输出信息管理器(OutgoingMessageManager)和输入队列组成;输出信息管理器收集发送的信息,序列化它、对它打包(bundle),在障栅同步阶段,bsp任务让信息在bsppeer之间做信息交换,解包并把解包后的信息方法队列中