前面的集群成员维护服务为我们提供了集群内全部成员的地址port等信息,能够通过MembershipService能够轻易从节点本地的成员列表获取集群全部的成员信息,有了这些成员信息后就能够使用可靠的TCP/IP协议进行通信了。这节讨论的正是实际中真正用于消息传送通道的相关机制及实现细节。
例如以下图,四个节点本地都拥有了一张集群成员的信息列表。这时节点1有这么一个需求:为了保证数据的安全可靠。在往自己的内存存放一份数据的同一时候还要同步到其它三个节点的内存中。节点1有一个专门负责发送的组件ChannelSender。首先从成员列表中获取其它三个节点的通信地址和port,再分别向此三个节点建立TCP/IP通道发送数据。其它节点有一个负责接收数据的服务,将数据更新到内存中。
最理想的状态是发送给节点2、3、4都成功了。这样从总体看来ChannelSender像是提供了一个多通道的平行发送方式。所以也称为平行发送器。但现实中并不能保证同一批的消息往全部节点发送都成功。有可能发送到节点3时由于某种原因失败了,而节点2、4都成功了,这时通常要採取一些策略来应对。比如又一次发送。
Tribes所使用的策略是优先进行若干次尝试发送。若干次失败后将向上抛出异常信息。异常信息包括哪些节点发送失败及其原因。默认的尝试次数是1次。
为确保数据确实被节点接收到。须要在应用层引入一个协议保证传输的可靠性,即是通知机制。发送者发送消息给接收者,接受者接收到后返回一个ACK表示自己已经接收成功。
Tribes中具体的协议报文定义例如以下:START_DATA(7bytes)+消息长度(4bytes)+消息长度(nbytes)+END_DATA(7bytes)。START_DATA为数据開始标识,为固定数组值70,76,84,50,48,48,50。END_DATA为数据结束标识。为固定数组值84,76,70,50,48,48,51,ACK_DATA表示通知报文。为固定数组值6,2,3。所以假设传输的是通知报文的话即为START_DATA+ACK_DATA的长度+ACK_DATA+END_DATA。
所以整个集群的消息同步例如以下图,节点1通过ChannelSender发送消息给节点2、3、4。发送成功的判定标准就是节点2、3、4返回给节点1一个ack标识,节点1接收到了则觉得发送成功。
为提高通信效率这里默认使用了NIO模式而非BIO模式(也可设置为BIO模式),使用NIO模式能统一管理全部通信的channel。避免了等待一个通道发送完成还有一个通道才干发送,假设逐个通信将导致堵塞IO时间非常长通信效率低下。
另外平行发送的过程须要一个锁保证消息的正确发送,比如有data1、data2、data3三个数据须要发送,应该是一个接一个数据包发送的而不能data1发一部分data2发一部分。
这节介绍了Tribes怎样向集群其它成员发送数据,通过本地获取其它成员节点的地址和port,再通过平行消息发送通道发送给其它节点。当中有ack机制和重发机制保证数据成功接收。