JGroups 介绍及配置说明
JGroups 简介
JGroups是一个基于Java语言的提供可靠多播(组播)的开发工具包。例如OSCache、JBossTreeCache、JBoss Infinispan都 是用的是 JGroups(或许还有更多)。在IP Multicast基础上提供可靠服务,也可以构建在TCP或者WAN上。主要是由Bela Ban开发,属于JBoss.org,在JBoss的网站也有一些相关文档。目前在SourceForge上还是比较活跃,经常保持更新。
JGroups 网站:JGroups – The JGroupsProject
JGroups 向导: http://www.jgroups.org/javagroupsnew/docs/tutorial/html_single/index.html
JGroups用户手册: http://www.jgroups.org/javagroupsnew/docs/manual/html_single/index.html
JGroup以IP多播为基础并且提供可靠性和群组功能。其中,可靠性包括
1,消息不丢失
2,大消息拆分和重组功能
3,保证消息有序性
4,消息原子性(某条消息要么全部成员都收到,或都收不到)
群组功能包括
1,群组成员知道群组内所有其他成员
2,当群组发生以下的事件,所有群组成员都能收到通知:
a) 新组员加入群
b) 旧组员离开群
c) 某现有组员意外脱离群
JGroups特点
JGroups功能十分强大,通过配置各种参数就可以充分利用它所提供的各项功能。JGroup最大的特点就是支持协议栈的可配置性,它本是实现了 基本的Java的协议栈实现,也就是最基本的消息广播的基础,同时支持附加协议栈的配置,消息的传递就是在这些协议栈之间相互传递,封装,检查,丢弃,重 发。JGroup可以基于TCP协议来实现消息广播,也可以通过UDP方式来广播消息,利弊不言而喻,TCP可靠,但是代价大,性能没有UDP来的 好,UDP速度快,代价小,但是消息的丢失率以及无序性有着很大的限制。但是JGroup在UDP方式的基础上,增加了协议栈的配置,通过配置上层的协 议,可以保证消息的重发,大包体的分解(同时保证消息包体顺序),组内机器的状态检测等功能。
IP多播与JGroups
IP多播与JGroups的区别如下:
Unreliable Reliable
Unicast UDP TCP
Multicast IP Multicast JGroups
单播(Unicast)通信中,一个发送者只发送给一个接收者。单播有UDP和TCP两种方式,UDP协议是不可靠的协议,传输中,包可能会丢 失,重复,无序且有大小限制。TCP其实也属于单播,但TCP是可靠的,提供重传机制防止包丢失,包的传输具有有序性,且TCP重组机制可以在传送大文件 前将文件分割成碎片。
在多播(Multicast)中,发送者向多个接收者发送信息,IP多播扩展自UDP协议,发送者将消息发送给制定的多播地址,接受者加入多播 地址且接收这些信息。受UDP协议限制,IP多播仍然是不可靠的,且没有考虑到群组功能(如无法判断哪些接收者加入了多播地址)。
JGroups扩展于可靠的单播传输机制(类似TCP)至多播,它在IP多播的基础上同时提供可靠性和群组功能。由于每个产品都有不同的可靠性 需求,所以,JGroups提供一种灵活的协议栈,这种协议栈可以让用户根据不同的可靠性指标,在对可靠性高且速度慢和可靠性差但速度快的效果之间作出折 衷的量化选择。
JGroups的配置
范例配置:
“UDP(mcast_addr=224.0.0.35;mcast_port=45566;ip_ttl=32;” +
“mcast_send_buf_size=150000;mcast_recv_buf_size=80000):” +
“PING(timeout=2000;num_initial_members=3):” +
“MERGE2(min_interval=5000;max_interval=10000):” +
“FD_SOCK:” +
“VERIFY_SUSPECT(timeout=1500):” +
“pbcast.STABLE(desired_avg_gossip=20000):” +
“pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):” +
“UNICAST(timeout=5000;min_wait_time=2000):” +
“FRAG(frag_size=4096;down_thread=false;up_thread=false):” +
“pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;” +
“shun=false;print_local_addr=true)”
UDP:使用IP多波协议来广播组内消息并且使用的是UDP包作为消息发送给独立的Member。
PING:是用多波协议来查找初始化的在线Member。
MERGE2:允许将子组合并到一个组。
FD_SOCK:基于Socket的错误检测(通过Member之间的环形检测来实现)。当发现有member失败就产生消息通知。
VERIFY_SUSPECT:双重检测member是否确实Dead,多了Suspect的状态。
Pbcast.STABLE:删除被全部member查看到的消息(作用就是如果在分布式的情况下,其中某些member没有看到,那么这条消息就不会被删除,会重发,保证消息广播的全局性)
Pbcast.NAKACK:保证消息的可靠性和FIFO(消息的顺序传递)。
UNICAST:类似于NAKACK的功能。
FRAG:大消息的拆分和组装。
Pbcast.GMS:组成员协议,响应加入离开组的消息以及新建view的消息。
UDP配置:
UDP广播模式可以配置成两种方式:使用UDP和常规IP多波传输。配置类似于范例中的配置。所有的组内成员都运行在一个host上,分布在一个 LAN内。但是这个需要确认的就是IP的多波传递是否允许穿越多个子网,通常情况下是不允许穿越多个子网的,因此就需要确保多个组内的member在一个 局域网中,并且可以相互间通信。
另一种模式就是使用UDP但是不使用IP多波传递。UDP和PING的配置都是基于IP的多波传递的,因此消息传递以及组内成员的初始化检测都是要 依靠于IP多波。因此这里提供了另外一种方式就是设定一个每一个member都能够访问到的机器,在这台机器上面设置一个GossipRouter,类似 于路由一样,每一个member的注册都直接在这台机器上的服务上管理。
需要配置的就是设置ip_mcast为false。同时需要配置gossip_host gossip_port gossip_refresh这三个参数(地址,端口,刷新一次GossipRouter的时间)。
然后就在那台服务器上运行GossipRouter程序:
java org.jgroups.stack.GossipRouter -port 5555 -bindaddress localhost
配置如下:
“UDP(ip_mcast=false;mcast_addr=224.0.0.35;mcast_port=45566;ip_ttl=32;” +
“mcast_send_buf_size=150000;mcast_recv_buf_size=80000):” +
“PING(gossip_host=localhost;gossip_port=5555;gossip_refresh=15000;” +
“timeout=2000;num_initial_members=3):” +
WAN中配置
当如果需要在WAN中使用JGroup的时候就需要配置TCP来替换UDP了。
“TCP(start_port=7800):” +
“TCPPING(initial_hosts=localhost[7800];port_range=5;timeout=
“num_initial_members=3;up_thread=true;down_thread=true):” +
“VERIFY_SUSPECT(timeout=1500;down_thread=false;up_thread=false):”
“pbcast.STABLE(desired_avg_gossip=20000;down_thread=false;up_
“pbcast.NAKACK(down_thread=true;up_thread=true;gc_lag=100;retransmit_
“pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;”
“print_local_addr=false;down_thread=true;up_thread=true)”;
FD 协议栈(Failure Detection)
FD的作用就是探测组内的成员是否还活着。当组内的成员被怀疑可能死掉了,那么SUSPECT消息就会传播到集群的每一个节点上。不过这个协议没有将crashed的member踢出去的功能,这个工作由GMS来做,它只是通知的功能。
FD是基于心跳消息检测来实现的,如果回复消息在timeout的规定时间内没有收到,那么就会宣布那个node被suspected,然后会被GMS给踢出去。一共三个参数作为配置项:
Timeout,max_tries,shun。前面两个不说了,最后一个十分重要。例如:一个组内有a,b,c,d四个成员,当d由于负荷过高没 有在timeout的时间内作出响应,导致被踢出组的时候,a,b,c的组员view中只有abc三个member,而d的view却还有abcd四个成 员,此时如果D再发消息给组内的成员,组内成员将会拒绝接受。那么如果设置shun为true的时候,D就重新加入组内在下面两种情况:1.ABC接受到 了D发过来的are-you-alive的检测消息。2.D自己收到了一个view消息,view内不包含D。(类似于重连机制)。这点很重要特别是在分 布式的环境中,当某些服务器的压力可能较高,配置的超时时间又不确定是否可以满足高负荷响应。记得要在GMS里面的shun也配置一样的情况。
FD_ALL也是基于简单的心跳协议,只不过是每个节点会向每一个member周期的发送心跳包,同时将会保存每个member的状态表。
FD_SOCK是基于环形的TCP Socket互联,相互监测来实现FD的功能的,每一个member都有自己的邻居,使得member组成一个环形的校验链。但是有几个缺点,第一当使用 多网卡机器的时候,2.2.8以前的版本就可能造成随机绑定ip的问题,以后可以指定bind_addr这个参数,明确邻居的ip。另外的缺点也就是我们 在实施过程中发现的问题,由于TCP的异常产生未必都能被检测到,同时例如网络问题等因素,往往这种FD很难保证真实的挂起出错的node,加之他是 ring的检测方式,会导致明明某个member已经dead了,但是由于没有检测到,导致后面再加入的member或者自己重启,都无法正常使 JGroup正常工作,不断地在重复join/leave的操作。(所以不建议使用这种模式)
JGroups 适合使用场合
服务器集群cluster、多服务器通讯、服务器replication(复制)等,分布式cache缓存。
参考文章
1.Jgroups配置与使用的学习笔记
2.JGroup 使用分享
3.JGroups之皮毛
4.JGroups 简介、适用场合、配置、程序例子Demo等完全使用指南
学习 扫盲