JGroups的可靠性保证

         Jgroups的传输协议有UDP、TCP 等,在这些传输协议上,为可靠性提供了UNICAST、UNICAST2、UNICAST3、pbcast.NAKACK、pbcast.NAKACK2五种自定义协议,其中前三种用于点对点传输,后两种用于多播。下边来看下其如何做到可靠性保证:

      1.   UNICAST:    主动重发、逐个确认,有如下3个步骤:

                  A                                                  B

           1):    |-------------send msg------------->|

           2):    |<----------- ack-----------------------|

           3):    |-------------retransmit------------->|

        假设是节点A向B节点发送消息

        1):  A向B发送消息,同时在内存中保存消息(用于重发)。

        2): 如果B收到消息会立刻返回一个确认ack,A收到确认后从内存中删除相应的信息。

        3): 在发送方A,会启动一个定时器定时检测有多少消息已被确认,没被确认的消息要逐个重发。

       这种方式的优缺点为:(+:优点  -: 缺点)

      +. 占用内存小,因为正常情况下,每条消息发送之后会立刻得到确认,然后立刻被丢弃。

      +. 简单。在传输过程丢失消息或者确认消息丢失,一定周期A会重发消息。

      -.  频繁的通信,每一条消息对应一条确认消息。

      -.  没有必要的消息重发。试想,如果因为网络延迟A没及时收到确认消息或者确认消息根本就丢失了,则A就重发消息,其实这是没必要的。

      1.   UNICAST2:    被动重发,主要是为了解决UNICAST的两个缺点,有如下3个步骤:

                  A                                                B

           1):    |-------------send msg------------>|

           2):    |<---interval need retransmit----|

           3):    |------------ retransmit------------>|

           4):    |<--------interval stable msg-----|

        假设是节点A向B节点发送消息

        1):  A向B发送消息,同时在内存中保存消息(用于重发)。

        2):  B收到消息不会返回确认消息,而是启动定时线程,定时检测有消息丢失就向A请求重发。

        3):  A收到重发请求,向B重发丢失的消息。

        4):  B定时计算收到消息总量大小到达一定量后,向A发送清理B已经收到的消息的请求,A收到消息则删除内存中B已经收到的消息。

       这种方式的优缺点为:(+:优点  -: 缺点):

      +.  减少没必要的消息确认。

      +.  消息传输速度快。

       -.  第一条和最后一条消息有可能没有可靠性保证。

            试想,如果A向B发送的第一条消息丢失了,直到B收到后续的消息才会检测到第一条消息丢失,才要求A重发,如果A只发送这一条消息呢?  类似的,如果A发送[1...5] 条消息,而消息5丢失,B只收到[1....4]消息,那么B无法要求A重发消息5,因为其不知道A到底发送了消息没有,只有B收到后续的消息才能检测到消息5丢失,才会要求A重发;或者直到B向A发送清理资源的消息后,A才重发消息5,而这过程很长。

        所以我们要对第一条消息和最后一条消息来进行特殊处理。对于第一条消息,接收方收到后一定要立刻返回确认消息,在发送方如果没有收到第一条消息的确认消息,则会定时重发第一条消息,如下图。 

                A                                                   B

           1):    |-------------send msg------------->|

           2):    |<-----------ack  first msg----------|

           3):    |-------------resend first msg---->|

           4):    |<------------need retransmit------|

           5):    |------------retransmit-------------->|

           6):    |<-------interval stable msg-------|

         对于最后一条消息的情况,接收方每次收到消息,在批量删除已被正确分发的消息后,向发送方发出一条清除资源的消息,发送方收到这条消息后重发丢失的消息。如下图:

                A                                                   B

           1):    |-------------send msg------------->|

           2):    |<-----------ack  first msg----------|

           3):    |-------------resend first msg---->|

           4):    |<------------stable msg------------|

           5):    |<------------need retransmit------|

           6):    |------------retransmit miss msg->|

           7):    |<-------interval stable msg-------|

       因为这个特殊处理,每次收到一条消息就会立刻发送一条清除资源消息,这么看来,和UNICAST中每次收到消息就返回确认消息,并没有减少网络通信?! 其实,还是有区别的,这里,在时间T0,如果收到5条消息,只发送一条清除资源消息。

      总体上看,UNICAST2并没有比UNICAST有太多的优势,反倒复杂很多。 如果把UNICAST和UNICAST2结合起来,会如何?  UNICAST3由此应运而生.

      1.   UNICAST:    UNICAST和UNICAST2的结合,目的是提供可靠性保证同时减少网络通信和资源。

                  A                                                             B

           1):    |-------------send msg----------------------->|

           2):    |<-----------interval ack-----------------------|

           3):    |<-----------interval need retransmit--------|

           4):    |--------------retransmit miss msg---------->|

           5):    |<-----------interval retransmit last   msg---|

        假设是节点A向B节点发送消息

        1):  A向B发送消息,同时在内存中保存消息(用于重发)。

        2):  B收到消息不是立刻返回确认消息ack,而是,定时向A发送确认,而且只确认最新的正确分发的消息 

        3):  B启动一个定时线程,定时检测有消息丢失就向A请求重发。   

        4):   A收到重发请求,向B重发丢失的消息。   

        5):  在发送方A,会启动一个定时器定时检测有多少消息已被确认,有消息没被确认则重发最后的那条消息(不像UNICAST重发所有消息)。

       所以,因为接收方周期且经过合并的发送确认消息,比UNICAST减少了很多网络通信。 而且,在发送方定时检测丢失消息,只重发最后的消息,减少没必要的消息重发,而且解决了UNICAST2的第一条及最后一条消息丢失的问题。

猜你喜欢

转载自saberhaha.iteye.com/blog/1944518