本章讨论怎么样正确使用和配置JGroups的协议栈协议,以及一些 JGroups 的高级概念。
1. jGroups协议栈
我们知道jGroups是一个可靠多播传输工具包,它能够为集群中成员提供点对点,点对组的通信,所有通信通过通道完成。通道基于协议栈之上,协议栈中协议各自有自己特别的功能,这些功能综合起来使通道通道具有完成多波传输的能力。协议栈中多种协议所具有的主要功能可以总结为:消息传输,集群发现,消息排序,消息无损耗传输,错误节点发现,集群成员管理。下图显示三个节点的集群,协议栈底层传输协议基于物理网络之上,通道基于协议栈之上,构建块接口和应用基于通道之上,如下:
接下来我们讨论这些被通道广泛使用的协议,根据他们各自的特定功能,我们讨论提供这些功能所需的关键属性,注意,这些属性只有在非常理解jGroups协议栈的情况下可以进行修改,所以我们不建议初学者对协议栈中协议的属性进行修改。我们讨论这些属性的目的是为了了解协议栈的功能。
1.1 传输协议
传输协议是协议栈最底层的协议,它负责从物理网络环境接收消息,将接收到的消息传递到协议栈中上层相邻的协议,以及将协议栈中上层协议传递下来的消息发送到物理网络。传输层协议主要包括UDP,TCP,TUNNEL。这些协议时独一的,在同一个协议栈中您只能配置一个传输层协议。
1.1.1 UDP
UDP使用IP多播(我们也可以配置使用多个单播)发送和接收数据,是默认推荐的传输层协议。如果您选择UDP作为您群组通信的传输协议,UDP配置如下:
<UDP mcast_port="${jgroups.udp.mcast_port:45588}" tos="8" ucast_recv_buf_size="20M" ucast_send_buf_size="640K" mcast_recv_buf_size="25M" mcast_send_buf_size="640K" loopback="true" discard_incompatible_packets="true" max_bundle_size="64K" max_bundle_timeout="30" ip_ttl="${jgroups.udp.ip_ttl:8}" enable_bundling="true" enable_diagnostics="true" thread_naming_pattern="cl" timer_type="new" timer.min_threads="4" timer.max_threads="10" timer.keep_alive_time="3000" timer.queue_max_size="500" thread_pool.enabled="true" thread_pool.min_threads="2" thread_pool.max_threads="8" thread_pool.keep_alive_time="5000" thread_pool.queue_enabled="true" thread_pool.queue_max_size="10000" thread_pool.rejection_policy="discard" oob_thread_pool.enabled="true" oob_thread_pool.min_threads="1" oob_thread_pool.max_threads="8" oob_thread_pool.keep_alive_time="5000" oob_thread_pool.queue_enabled="false" oob_thread_pool.queue_max_size="100" oob_thread_pool.rejection_policy="Run"/>
如上我们可以发现UDP传输协议包括很多配置选项,接下来我们首先列出UDP特有的配置属性,随后列出UDP,TCP,TUNNEL所共有的配置项。UDP 特有的属性:
- ip_mcast确定是否使用IP多播,默认值为true,如果设为false,多个单播通信的模式(发送多个单播包)代替多播通信模式。所有包的发送都是通过UDP协议发送UDP数据包
- mcast_addr 确定多播通信的地址 ,如果配置时省略了这个属性,则默认的配置为288.11.11.11
- mcast_port 确定多播通信的端口,如果这个属性被省略了则默认的端口为45588
- mcast_send_buf_size, mcast_recv_buf_size,,ucast_send_buf_size ,ucast_recv_buf_size 定义了jGroups发送和接收多播和单播包的大小,jGroups在发送和接收多播和单播包时根据这些配置向操作系统发送请求。如果这些属性配置太小,容易在Java层面造成丢包等现象,但多播和单播运行最大包的大小在操作系统层面也有限制,所以为了使jGroups高效率工作我们需要在操作系统层面做优化配置,随后我们在高级概念部分会讨论此问题
- bind_port确定单播接收套接字绑定的端口,默认为0,即使用短期的端口
- port_range确定如果bind_port确定的端口不可用重新尝试的端口,默认为1
- ip_ttl确定IP多播包的生存周期(TTL),TTL是多播通信中常见的概念,主要指多播通信中一个包被允许的网络跳跃次数,超过这一值后网络设备将包丢弃
- tos 确定发送多播和单播包的类
UDP,TCP,TUNNEL所共有的属性:
- singleton_name提供一个单例的传输层配置项,被ChannelFactory使用,如果传输层配置了此属性,ChannelFactory将使创建的通道共享传输层协议,随后我们在高级概念部分会讨论此属性
- bind_addr确定一个发送和接收消息的地址,默认,jGroups使用JVM系统参数jgroups.bind_addr来确定此地址
- receive_on_all_interfaces确定此节点是否监听所有多播地址(多个网卡),默认值为false,该属性重写了bind_addr定义的接收多播的地址,但节点发送多播地址任由bind_addr定义
- send_on_all_interfaces确定此节点是否通过您本地所有网卡发送多播消息,如果您本地有N个网卡(即N个IP地址),则同一个多播包被发送了N此,使用此属性可以避免此情况
- receive_interfaces确定接收多播包的地址列表,多播接收的套接字将监听于这些接口,这些地址是用逗号隔开的IP地址或网卡名,例如:192.168.5.1,eth1,127.0.0.1
- send_interfaces确定发送多播消息的地址,多播发送套接字将通过这些地址发送多播消息,这个地址同样是用逗号隔开的IP地址或网卡名,例如:192.168.5.1,eth1,127.0.0.1,这说明同一个多播包将在这三个地址上同时发送,即一个包被发送了3次
- enable_bundling,max_bundle_size,max_bundle_time确定是否允许消息捆绑。如果enable_bundling只为true,传输层协议将要发送的消息放在一个队列中,直到队列的大小达到max_bundle_size,接着传输层协议将所有队列中的消息捆绑成一个大消息然后发送。当然在消息队列没有达到max_bundle_size之前,队列中的消息等待时间超过max_bundle_time,则传输协议同样将队列中的消息捆绑成一个发消息发送。在接收端,传输层将这个大消息分裂然后传递该高层协议处理。该属性的默认值为true,即JGroups默认允许消息捆绑,消息捆绑的大小为64000字节,超时时间为30毫秒。JGroups提供API接口指定是否进行消息捆绑,RequestOptions.setFlags(Message.DONT_BUNDLE)可以使要发送的消息不进行消息捆绑发送机制,例如DONT_BUNDLE标记的消息,传输层协议不将其放入等待队列,会立即发送。
- loopback确定线程给群组发送消息是否携带消息备份(消息发送到组中总是也发送到者自己)。如果此属性职位false,发送线程不携带消息,传输层协议读取网络中的消息,使用传输层线程池中线程传递消息。如果此属性值为true,则运行通道接收自己的消息,以防网卡出现故障
- discard_incompatible_packets确定是否忽略群组中的成员使用其他版本的JGroups发送消息。群组中的任何一个消息都绑定着一个JGroups版本,如果此值得设定为true,则接收到的消息中版本不匹配的消息将被忽略,会员相应的警告日志输出,此属性的默认值为true
- enable_diagnostics,diagnostics_addr,diagnostics_port 确定是否传输层打开一个监听在地址diagnostics_addr和端口diagnostics_port上,如果该属性为true则允许监听请求连接
- thread_pool.*定义JGroups用来处理消息,将消息传递向高层协议的线程池的属性,这些属性用来初始化java.util.concurrent.T hreadPoolExecutorService,在之前的配置中我们定义连接池的最小线程数为2,最大连接数为8,如果多于最小线程数个线程创建,如果线程携带返回则将等待5000毫秒后分配一个新的消息,如果没有线程可供携带消息,消息则被放置在一个队列中,直到队列的大小为10000,如果还没有线程可用则消息被丢弃。
- oob_thread_pool.*与thread_pool类似,初始化java.util.concurrent.T hreadPoolExecutorService,用来将接收到的消息传递到高层协议。在这里的线程用来传递Out-Of-Band (OOB)消息,OOB消息是脱离顺序传递即NAKACK 和UNICAST相关的消息,OOB消息是JGroups协议内部使用,同样也可以被应用程序使用。例如,JBossCache在REPL_SYNC模式下OOB消息用于2象限提交中的第二象限。
1.1.2 TCP
可供选择的,JGroups构建群组通信业可以基于TCP连接。与UDP相比,TCP则需要更多的网络流量,特别是当群组的成员的数量较多时。从根本上来说,TCP是单播协议,发送多播消息,JGroups使用多个TCP单播。如果要使用TCP作为传输协议,则需要在JGroups协议栈中配置TCP协议,如下是一个配置的例子:
<TCP singleton_name="tcp" start_port="7800" end_port="7800"/>
如下为TCP协议专有的属性:
- start_port,end_port定义了应用所能绑定的TCP端口的范围,服务器端监听的套接字绑定start_port开始的第一个可用的端口,如果end_port之前的所有端口不能够使用(被其它监听套接字使用),JGroups将会抛出异常。如果没有配置end_port,或end_port的值小于start_port,则端口的范围没有限制;如果start_port的值等于end_port,则JGroups使用唯一确定的端口,即在上面的配置中唯一的端口号为7800。JGroups提供的默认配置是7800,如果该值设为0则需要操作系统选择一个随机端口(MPING和TCPGOSSIP协议使用)。
- bind_port它相当于start_port的化名,如果我们配置此属性,则start_port的值为它
- recv_buf_size, send_buf_size定义了接收和发送缓冲区的大小,一般我们建议配置一个较大的缓冲区,这样我们不会因为接收的消息太大而导致消息丢失
- conn_expire_time定义了最大过期时间(毫秒),即多长时间如果没有消息接收连接被连接释放器关闭
- reaper_interval定义了连接释放器运行的时间间隔(毫秒),如果该属性的值为零,连接释放器释放连接的功能被禁止,如果该属性大于零,则每隔属性值定义的值进行一次连接释放。该属性的默认值为零
- sock_conn_timeout定义了Java套接字创建的最大时间,如果进行初始化节点发现,且该节点异常,则不处于一只等待的状态,而是在等待该时间后去发现另外的节点。该属性默认值为2000
- use_send_queues定义每个连接是否使用自己独自的发送队列。这个可以预防通信中一方如果发生异常通信一只处于等待状态。该属性默认值为true
- external_addr定义了对群组成员发送广播的外部的IP地址。特别在有网络交换,即一个节点位于一个私有网络中,这个私有网络位于防火墙之后,在这种情况下该属性特别有用。如果不设定external_addr属性,如果你的节点位于防火墙之后,则你的节点不能够发送广播给防火墙外的群组成员
- skip_suspected_members确定是否单播消息应该发送到异常的节点,该属性默认值为true
- tcp_nodelay确定TCP_NODELAY,TCP默认会对小消息绑定成一个大消息然后发送,如果我们进行异步群组通信我们最后应该禁止TCP的这种延迟机制,该属性的值默认为false
1.1.3 TUNNEL
TUNNEL协议使用一个外部路由进程发送消息。外部的路由进程可以通过运行org.jgroups.stack.GossipRouter的main方法启动。群组中的任何节点都要注册到这个路由,任何消息都首先发送到路由,然后路由给他的目的接收者。TUNNEL协议可以用来建立防火墙两点节点的通信,一个节点穿过防火墙于路由进程建立连接(使用80端口)将消息方式给防火墙对面的节点,同样使用与路由进程的TCP连接防火墙对面节点发送的消息。TUNNEL协议配置大致如下:
<TUNNEL singleton_nam e="tunnel" router_port="12001" router_host="192.168.5.1"/>
TUNNEL协议所有的属性如下:
- router_host指定路由进程的运行地址
- router_port指定路由进程监听的端口
- reconnect_interval指定TUNNEL尝试连接到路由进程的的时间间隔(毫秒),如果TUNNEL连接路由进程失败,该属性设定了时间间隔,TUNNEL则会每隔这个时间间隔尝试连接路由进程
1.2 发现协议
当一个节点上的通道第一次连接,它必须探测发现是否有其它节点运行着一致的通道,即找到集群的协调者(第一个创建的节点为协调者,负责新创建的节点加入集群)。发现协议用来发现集群中活跃的节点及集群的协调者。这些信息接着传递给集群成员管理协议(GMS),GMS协议与协调者的GMS通信,将新加入的节点加入到集群。消息关于GMS的描述我们随后介绍。发现协议通常也协助合并协议(MERGE2)处理集群分裂的情形。关于MERGE2同样我们随后会做详细的介绍。发现协议位于传输协议之上,因此需要传输协议的不同使用相应的发现协议,接下来我们列出jGroups中用到的发现协议。
1.2.1 PING
发现协议PING既可以工作于发生多播PING到一个IP多播地址,也可以连接到TUNNEL的路由进程。也就是说发现协议PING位于传输协议UDP或TUNNEL之上。任意一个节点对PING消息的反馈消息包括协调者的地址和自己的地址,JOIN PING消息发送后等待timeout属性定义的时间或num_initial_members属性定义的节点回复后,该加入的节点会根据反馈消息确定协调者,发送JOIN消息, 如果没有收到任何反馈,会认为自己是集群中第一个节点为协调者。
如下为PING基于IP多播的配置:
<PING tim eout="2000" num _initial_mem bers="3"/>
如下是PING基于TUNNEL路由进程的配置:
<PING gossip_host="localhost" gossip_port="1234" timeout="2000" num _initial_mem bers="3"/>
PING协议的属性如下:
- timeout确定最大等待num_initial_members个成员的响应时间,该属性的默认值为3000
- num_initial_members等待最小数量的成员响应的个数,这个响应个数具体指timeout之前的响应成员最小个数,默认为2
- gossip_host确定TUNNEL路由进程运行的地址
- gossip_port确定TUNNEL路由进程监听的端口
- gossip_refresh确定拿到TUNNEL路由进程的时间间隔(毫秒),默认为20000
- initial_hosts是用逗号隔开的地址和端口(例如host1[12345],host2[23456])确定PING的目的地址,默认为空,表示IP多播被使用。如果该属性列出地址,你必须列出所有集群地址,不能指定部分已知的地址,合并协议(MERGE2)将不能够可靠地工作
如果gossip_host 和 gossip_port属性被定义,集群使用PING路由进程来完成初始的发现;如果initial_hosts被定义,集群PING定义好的地址来完成初始的发现;其他情况IP多播被使用来完成初始化发现。
1.2.2 TCPGOSSIP
TCPGOSSIP协议只能和路由消息一起工作。它和PING消息使用gossip_host 和 gossip_port属性提供的功能一样,它可位于TCP和UDP传输协议之上,如下为一配置的示例:
<TCPGOSSIP timeout="2000" num_initial_m em bers="3" initial_hosts="192.168.5.1[12000],192.168.0.2[12000]"/>
TCPGOSSIP协议的所有属性如下:
- timeout确定最大等待num_initial_members个成员的响应时间,该属性的默认值为3000
- num_initial_members等待最小数量的成员响应的个数,这个响应个数具体指timeout之前的响应成员最小个数,默认为2
- initial_hosts是用逗号隔开的地址和端口(例如host1[12345],host2[23456])用来注册路由进程
1.2.3 TCPPING
TCPPING 协议属性包括要发现的成员地址,通过Ping这些已知的成员完成发现。TCPPING协议基于TCP传输协议之上。如下为TCPPING协议属性配置示例。
<TCPPING timeout="2000" num_initial_members="3" initial_hosts="hosta[2300],hostb[3400],hostc[4500]" max_dynamic_hosts="3" port_range="3">
具体属性包括:
- timeout 确定等待PING num_initial_members个成员返回的最大等待时间(毫秒),默认值为3000
- num_initial_members 确定要等待返回相应的最小成员个数,直到timeout发生,该属性的默认值为2
- initial_hosts 逗号分开的地址,例如host1[1234 5],host2[23456],该属性确定发现协议TCPPING 要PING的地址
- max_dynamic_hosts 确定最大可以动态加入到集群的地址个数(默认为0)。如果动态加入集群的特性被禁止,则要确保<initial_hosts>属性列出了所有成员地址,否则有些成员在集群启动时会遗漏某些成员
- port_range 确定连续的端口号当进行初始化成员关系。起始端口为initial_hosts确定的端口号,如上initial_hosts的定义,TCPPING 协议将尝试PING hosta[2300], hosta[2301],hosta[2302], hostb[3400], hostb[3401],hostb[3402],hostc[4500],hostc[4 501],及 hostc[4502]
1.2.4 MPING
MPING使用IP多播发现初始的成员关系。不像其他发现协议需要借助于传输层协议发送发现消息,MPING通过它自己的套接字发送和接收多播消息。由于使用MPING协议通过多播消息完成初始发现,所以它可以使用与任何传输协议,但是它最常被TCP协议使用。我们知道TCPPING 协议需要通过initial_hosts属性明确的列出要初始发现的地址,但MPING则不需要。MPING通常用做TCP做传输协议,IP多播做为初始发现的场景,如下为MPING协议配置示例。
<MPING timeout="2000" num_initial_members="3" bind_to_all_interfaces="true" mcast_addr="228.8.8.8" mcast_port="7500" ip_ttl="8"/>
相关MPING属性元素列表:
- timeout 确定初始成员列表时等待任意返回的最大时间(毫秒)。默认值为3000
- num_initial_members确定要等待返回相应的最小成员个数,直到timeout发生,该属性的默认值为2
- bind_addr 确定发送和接收多播消息的地址,JGroups默认使用系统参数jgroups.bind_addr来确实该属性的值
- bind_to_all_interfaces 重写bind_addr属性,如果多个多播地址存在,我们则使用多个多播地址
- mcast_addr,mcast_port, ip_ttl 这些属性与UDP协议中的描述相同
1.3 错误探测协议
错误探测协议用来发现集群中发生错误的节点。当某一个节点发生错误被探测到,一个怀疑确认会发生,当怀疑确认完成后该节点认为是死的(发生错误),集群则会更新自己的成员关系视图,群组中新的消息就不会发向该发生错误的节点。错误探测协议也是JGroups配置<config>的子元素,接下来我们明细这些协议。
1.3.1 FD
FD协议基于心跳消息(are-you-alive)。该协议需要任意一个节点周期性的Ping它的邻居节点,如果邻居节点没有返回,发生心跳消息的节点发送SUSPECT消息给集群,集群协调者接收到SUSPECT消息后验证怀疑的节点是否死掉(VERIFY_SUSPECT),如果节点被确认为死掉,协调者更新集群成员关系视图,死掉的节点被移除。如下为FD配置示例。
<FD timeout="6000" max_tries="5" shun="true"/>
相关FD属性元素列表如下:
- timeout 确定等待接收心跳消息返回的最大时间 (毫秒),该属性的默认值为3000
- max_tries 确定等待超时重发心跳消息的次数,重发max_tries次数后如果还不能收到心跳消息的返回,则认为该节点发生异常,发送SUSPECT消息给集群,该属性的默认值为2
- shun 确定发送错误的节点在重新加入集群之前是否可以向集群发送消息。发生异常的节点需要通过发现协议重新加入集群,JGroups有这样的功能,即发送错误的节点重新获取集群状态加入集群
1.3.2 FD_SOCK
错误探测协议FD_SOCK基于群组成员创建的TCP套接字环。集群中的任何一个节点都连接到它的邻居,集群中第一个节点连接到第二个节点,第二个节点连接到第三个节点,这样最后一个节点连接到第一个节点。这样如果某一个节点发送异常,它的邻居节点会发现异常,检测到错误。FD_SOCK 可以不包含任何属性,如下为FD_SOCK配置示例。
相关FD_SOCK属性元素列表如下:
- bind_addr 确定发送和接收多播消息的地址,JGroups默认使用系统参数jgroups.bind_addr来确实该属性的值
1.3.3 VERIFY_SUSPECT
VERIFY_SUSPECT协议确认被怀疑的节点是否确实死掉了(通过发送确认消息)。这个操作是被集群的协调者执行的。如果确认节点死掉,则该节点将会被异常集群成员列表视图。如下为VERIFY_SUSPECT协议属性配置。
<VERIFY_SUSPECT timeout="1500"/>
1.4 可靠传输协议
可靠传输协议确保群组消息确实可靠传递,并以正确的顺序(先入先出,FIFO)传递到目的地。可靠的消息传递基础是正面和非正面的确认消息(ACK和NAK)。在ACK模式中,发送者重新发送该消息,直到从接收者接收到确认。在NAK模式,接收者请求发送者重新传输,直到发现了缺失的消息。
1.4.1 UNICAST
UNICAST协议在发送单播消息时使用。UNICAST协议使用ACK模式,它的配置也在JGroups <config>中,注意,如果底层传输协议使用TCP,UNICAST则不需要配置,因为TCP传输本身就可以保证消息传输时能够FIFO。如下为UNICAST协议配置示例。
<UNICAST timeout="300,600,1200,2400,3600"/>
UNICAST协议只包含一个属性:
- timeout 确定重新传输的超时时间(毫秒)。例如,如果timeout值为100,200,400,800,如果消息发送者在等待100毫秒还没有接收到消息接收者的ACK消息,则消息发送者重新发送消息(第一次重发),消息发送者继续等待200毫秒仍然没有接收到ACK消息,则消息发送者再次重新发送消息(第二次重发),这样直到等待800毫秒进行第四次重发。如果第一次重发的等待时间很小,消息可能被重发两次(发送者收到ACK消息大于等待时间)。等待时间较大(如1000,2000,4000)可以提高网络传输性能,特别是在网络环境可以确保UDP数据包不会丢失的环境中。当然如果时间较大,且UDP数据包丢失频繁发生,在这种环境下传输性能很低,因为重传的等待时间很大。
1.4.2 NAKACK
NAKACK协议在发送多播消息时使用。NAKACK协议使用NAK模式。在这种协议下,每个消息绑定一个序列号,消息接收者根据序列号确保消息按正确的顺序传递。如果接收者发现了一个序列号的缺失,接收者安排一个周期性的任务去要求发送者重新发送该序列号的消息,当缺失的序列号的消息收到,则任务取消。NAKACK协议也是配置在JGroups <config>中,如下为一配置示例。
<pbcast.NAKACK max_xmit_size="60000" use_mcast_xmit="false" retransmit_timeout="300,600,1200,2400,4800" gc_lag="0" discard_delivered_msgs="true"/>
相关pbcast.NAKACK属性元素列表如下:
- retransmit_timeout 定义了一系列超时时间(毫秒),接收者发现某一序列号消息丢失,消息重发请求发送给消息发送者,消息接收者等待超时后重新发送消息重发请求给发送者,该属性定义了这个超时时间,而且依次递增(第二次等待超时时间大于第一次)
- use_mcast_xmit 确定消息发送者是否重发消息给整个集群,还是只重发消息给请求重发消息的接收者
- max_xmit_size 确定捆绑重发消息的大小。如果很多消息需要被重发,这些重发消息可能被捆绑成一个大消息然后重发
- discard_delivered_msgs 确定是否在接收端清除已接收的消息。默认情况下,消息接受者将接收到的消息保存起来,放置原始的发送者发生异常或离开集群后,消息可以继续重发。如果我们只需要消息发送者重发消息,那么我们可以在接收端清除接收到的消息,该中情况我们需要设定此属性的值为true
- gc_lag 确保在周期性清除协议(随后有消息介绍)提示所有节点已经收到了消息后仍然保留在发送者内存中的消息个数。该属性默认值为20
1.5 GMS
GMS即群组成员关系协议,该协议时JGroups协议栈中的重要协议,它维护者一个活着节点的列表。GMS负责群组成员加入和离开群组的请求,同时它也处理错误探测协议发送的SUSPECT协议。GMS协议也是配置在JGroups <config>中,如下为一配置示例。
<pbcast.GMS print_local_addr="true" join_tim eout="3000" join_retry_tim eout="2000" shun="true" view_bundling="true"/>
相关pbcast.GMS属性元素列表如下:
- join_timeout 确定新节点加入请求成功的最大时间(毫秒),如果超时随后重新尝试
- join_retry_timeout 确定新节点加入请求失败后重新加入请求的超时时间(毫秒)
- print_local_addr 确定是否在启动时输出自己的地址发哦标准输出
- shun 确定一个节点在接收到集群视图表明自己不是集群的节点时将自己从集群中断开
- disable_initial_coord 确定是否阻止该节点在集群初始化(初始化通道)时成为集群的协调者。注意该属性只是在集群初始化时起作用,但在集群初始化完成后不起作用,即如果集群中当前协调者离开集群,重新分配协调者时该属性不起作用
- view_bundling确定是否允许同时接收到多个加入或离开请求。这样集群视图只更新一次就完成多个请求,这样更有效率
1.6 FC
FC即流量控制协议。流量控制协议用来在集群中调节消息发送的比率和消息接收的比率。如果消息发送者的节点发送的速度很快超过了消息接收者节点处理消息的速度,这可能会导致接收到陷入异常或某些消息丢失,流量控制协议负责调解此类状况。事实上,JGroups流量控制协议基于类似信贷的设计,一开始消息发送者和消息接收者有相同的贷款(字节数),发送者减少贷款值通过自己发送的字节数,接收者已接收到自己累加自己的贷款,如果发送者贷款降低到某一阈值,接收者发送一些贷款给发送者,如果发送者用完自己的贷款,则发送者处于阻塞状态直到接收到接收者的贷款。流量控制协议也是配置在JGroups <config>中,如下为一配置示例。
<FC max_credits="2000000" min_threshold="0.10" ignore_synchronous_response="true"/>
可配置的流量控制协议属性如下:
- max_credits 确定最大的信贷系统的贷款值(字节),该属性定义的值应该小于JVM启动时分配的堆的大小
- min_credits 确定信贷系统的贷款最小值,如果发送者贷款降低到这个值则接收者要发送贷款给发送者
- min_threshold 确定计算信贷系统的贷款最小值的比率,信贷系统的贷款最小值=max_credits* min_threshold,如果min_threshold定义,min_credits属性定义的信贷系统的贷款最小值被重写
- ignore_synchronous_response 确定JGroups线程是否在流程控制阻塞的情况下携带消息到应用,禁止携带可能会导致大量的锁现象发生,所以我们推荐此属性的值为true
1.7 分裂协议
当一个消息的大小大于某一确定的值时,分裂协议将消息分裂成多个小消息,然后进行发送;而在接收端,同样分裂协议将分裂的消息进行重组。不管多播还是单播发送消息,分裂协议都可以起作用。分裂协议是JGroups <config>中的一个元素(FRAG2),如下为一配置示例。
<FRAG2 frag_size="60000"/>
FRAG2协议的可配置属性如下:
- frag_size 确定消息被分裂协议分裂的临界点(字节),即如上配置,当要发送的消息大于60000字节时,消息被分裂。如果JGroups协议栈配置UDP作为底层的传输协议,则这个属性的值必须小于64000字节(64KB),因为UDP允许的传输的最大数据包为64000字节(64KB)。如果JGroups协议栈配置TCP作为底层的传输协议,这个属性的值必须小于流量控制协议的max_credits属性定义的字节大小
1.8 状态交换协议
状态交换协议负责从已经存在的节点(集群协调者)交换状态到新加入的节点。状态交换协议也是JGroups 配置<config>中的一个元素(pbcast.STATE_TRANSFER),状态交换协议没有任何可配置的属性,如下为一配置示例。
<pbcast.STATE_TRANSFER/>
1.9 分布式垃圾回收协议
在JGroups中,所有节点必须保持已经接收到的消息以防止错误所需要的消息重传。但是如果我们永远保存接收到的消息,则我们会面临内存溢出的问题。分布式垃圾回收协议负责周期性的释放所有节点上已经被所有节点收到的消息,从而达到回收各个节点上内存的目的。分布式垃圾回收协议也是JGroups 配置<config>中的一个元素(pbcast.STABLE),如下为一配置示例。
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="5000" max_bytes="400000"/>
pbcast.STABLE协议的可配置属性如下:
- desired_avg_gossip 确定分布式垃圾回收的时间间隔(毫秒)。如果此属性的值为0,则禁止分布式垃圾回收机制
- max_bytes 确定激活分布式垃圾回收的最大接收消息的字节数。如果此属性值设为0则禁止此功能。如果集群消息交换比较频繁则此属性的设置是非常有必要的
- stability_delay 确定集群中节点在垃圾回收结束之前发送STABILITY消息的随即推迟的时间间隔(毫秒)。如果与max_bytes属性同时使用,则该属性应设定一个较小的值
1.10 合并协议
如果网络异常发生,集群可能被分割成多个区域而形成多个集群(多个协调者)。合并协议负责将分割成的多个区域重新合并成一个集群(通过多个协调者之间的沟通)。合并协议是JGroups 配置<config>中的一个元素(MERGE2),如下为一配置示例。
<MERGE2 max_interval="10000" min_interval="2000"/>
MERGE2协议的可配置属性如下:
- max_interval确定等待发生合并消息的最大时间(毫秒)
- min_interval确定等待发生合并消息的最小时间(毫秒)
JGroups选择max_interval与min_interval之间的一个随机值周期性的发送合并消息。
Comments