为了进一步深入了解JBoss-cache,所以觉得有必要好好研究一下JGroups。
要了解JGroups自然不能对Multicast毫无概念,虽然以前有前后多次看过相关文档,但是都没有留下什么系统的东西,所以这次决定从头看起,并写下这个指南。以下大部分内容来自互联网,尤其是www.jgroups.org。
2.什么是Multicast
Multicast是一种同时向多台机器发送数据的机制。
Multicast使用224.0.0.0到 239.255.255.255
这段IP来传送数据,这段IP地址是保留的,发送到这上面的数据不会通过你的子网转发。
在RFC-1060中定义了一部分预留的组播地址,使用时应注意不要重复。
一些比较特别的组播地址:(更多内容请查看RFC-1060)
1)224.0.0.0 这个是保留地址,不会被指定到任何的组播组
2)224.0.0.1 这个地址在所有的主机上被指定为一个永久组播组,这个地址可以用来找到本地子网内所有的组播主机。
使用ping224.0.0.1可以查看这些地址
在一个组播中的所有主机使用一个相同的组播地址,它们被称为一个组(Group),组中的成员是动态的,他们可以随时加入或者离开组。每台主机可以同时是多个组的成员,也可以不属于任何一个组。比较特别的是,并不是只有组中的成员才可以给组发送数据。
组分为两种,一种是永久性的,一种是动态的。对于永久性的组,他们拥有一个众所周知的管理IP地址,这个地址不是组中的成员,它是永久的。永久性的组可以
拥有任何数量的成员,甚至没有成员。而动态组只有在拥有成员的时候才存在。JGroups使用的就是动态组来实现组播数据的。
3.什么是JGroups
JGroups是一个可靠的组播通讯工具集(需要说明的是,这并不是说必须要使用IP Multicast,JGroups也可以使用TCP来实现)。JGroups可以用来创建一个组,这个组中的成员可以给其他成员发送消息。
Jgroups的主要功能如下:
1.创建和删除组,组成员可以分布在局域网或广域网中。
2.组成员加入和离开组3.成员关系的自动侦测并通知成员的加入,离开和丢失(原文是crashed,大意就是说没有通知的离开吧
4.侦测并删除丢失的成员
5.发送和接收成员到组的消息(点到多点)
6.发送和接收成员到成员的消息(点到点)
JGroups使用灵活的协议栈,这也是JGroups最强大(the most powerful)的功能,它允许开发人员配置协议栈来适用于他们自己的应用需求和网络特征。这样做的好处在于,开发人员只需要关注他们使用到的协议。通过组合和匹配各种协议来满足各种不同应用的需求。JGroups实现了一系列的协议(开发人员也可以编写他们自己的协议),例如:
传输协议:UDP(IP Multicast),TCP,JMS
分块协议:FRAG和FRAG2用来将大消息分块发送
可靠传输协议:UNICAST和NAKACK
失败侦测:FD(passive failure detection),VERIFY_SUSPECT。自动将丢失的成员排除到成员列表以外。
排序协议:Atomic(发送所有或者全部不发),FIFO, Causal, Total Order (序列或基于分块)
成员协议:GMS(Group membership)用来处理成员的加入和离开
加密:AES/ECB/PKCS5Padding/RSA... 对传输的数据进行加密
其他还包括流量控制,统计等
*以上主要内容翻译自http://www.jgroups.org/javagroupsnew/docs/index.html
4.JGroups详解
注意:以下内容基于JGroups2.2,获取最新信息请访问www.jgroups.org
4.1. 基本解构
讲解之前我们先来看一个图,有一个直观的概念先
其中有几个比较重要的概念需要解释一下:
Channel
一个Channel表示一个组播通讯的endpoint。客户端通过连接一个组播地址的Channel来加入一个组。
Channel的FSM(状态机)大致如下:
- unconnected:表示这个Channel创建了
- connected:表示这个Channel已经连接到一个组,并可以发送和接收消息
- unconnected:表示这个Channel从一个组断开,并可以加入其他组
- closed:表示这个Channel已经关闭
一个Channel同时只能有一个发送者发送消息(同步的),当然一个应用可以有多个Channel。可以使用Channel上send和receive(拉,可以通过linstener来实现推的模式)方法来发送和接收消息。
Protocol Stack
协议栈管理一组协议,并维持他们的上下关系,它负责创建所有的协议,并初始化和启动它们。它同时负责将从协议上接收到的消息发送到注册的对象上,比如Channel和GMP,并将来自这些对象的消息下发到协议栈上。
协议栈可以通过Configurator来设置,初始化,停止和删除协议。
Event
用来在协议层之间传递消息
Protocol
协议层被按顺序的放置到协议栈中。Event被从底层向上传递,比如UDP层接收到一个消息后,此消息将被当作一个Event向上层传递。每层协议都将按顺序处理Event,直到有一层发送一个响应或者丢弃这个消息。发送消息同样,只是从上而下调用协议层。
每个协议都包括两个FIFO的队列,一个存放用来向下消息,一个用来存放向上的。无论消息上行还是下行都将先进入队列,并有相应的队列处理(up-handler和down-handler)来处理它们(调用这个协议上的 up和down方法),协议的实现只需要实现相应的up和down方法,而无须关心这些内容。
有一点要特别指出的是,消息在协议层之间传递是按照FIFO顺序的,所有的协议实现必须保证这一点。
4.2. 协议详解
JGroups中有非常多的协议实现(约50种),这里不可能全部拿来讲,我挑选一些比较常用的协议来讲,其他的可以通过查看Javadoc或者JGroups的源代码来了解。
说明:以下协议中讲到到参数也只是常用参数,具体内容请查阅javadoc。
数据传输及网络层协议
这个协议是协议栈中相当重要的部分,它来完成数据的发送和接收。
JMS
使用Java Message Service(JMS)实现的传输协议,此协议依赖JMS服务器来分发消息,JMS服务器将发消息发送到特定的Topic下,所有订阅此Topic的将收到消息。关于
JMS请访问:http://java.sun.com/products/jms/需要注意的是当使用JMS作为数据传输协议时应避免使用那些打开服务器连接的协议,比如FD_SOCKET。这JMS里FD比FD_SOCKET更合适。(关于FD和FD_SOCKET请看下面的介绍)
参数表如下:
名称 | 类型 | 默认值 | 描述 |
topicName | String | 必选 | 完整的JNDI名称,用来表记发送消息的Topic |
cf | String | ConnectionFactory | 用来创建到Topic连接的ConnectionFactory的JNDI名称 |
jndiCtx | String | -Djava.naming.factory.initial | JNDI |
providerURL | String | -Djava.naming.provider.url | JNDI |
ttl | int | 0 |
TP
这是一个传输协议的抽象类,TCP和UDP都是从这里继承而来,主要将将它的一些配置,这些配置都可以用再UDP和TCP协议上。
参数表如下:
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
bind_addr | String | -Dbind.address=addr | 选择使用那个本地NIC来进行数据传输 |
discard_incompatible_packets | boolean | false | 是否屏蔽不兼容得数据包,只JGroups得版本,通常小版本不会有文体,如果将此设置为 true则表示必须完全相同得版本的消息才接收。< /P> |
loopback | boolean | false | 如果设置为true那么自己发送给自己的消息将被特殊处理。< style="font-family:Vera Sans YuanTi, serif;">unicast消息将被立刻回发,multicast消息则会先在本地进行一个拷贝,真的消息回来是会被丢弃,拷贝的消息将被回发。 对于Window |
use_incoming_packet_handler | boolean | false | 如果设置成true,那么消息接收线程将把接收到的消息放入临时队列,并有其他线程来处理反序列化和上发等处理。这可以节约接收线程的处理时间。 |
use_outgoing_packet_handler | boolean | false | 类似上面的,只是针对发送的消息 |
enable_bundling | boolean | false | 是否支持消息合并,即把小的消息和并成大消息来发送。 |
max_bundle_size | int | 由 AUTOCONF监测 | |
max_bundle_timeout | int | 20(ms) |
TCP,TCP_NIO
使用TCP实现的传输协议,创建一个ServerSocket来监听消息。对于每个连接(accept())都会创建一个线程来监听其消息,所有的外发的
消息对于每个目标地址都使用独立的线程来发送,这些线程是复用的。使用ConectionTable来实现以上机制。
NIO使用java.nio实现,关于NIO请访问:http://java.sun.com/j2se/1.4.2/docs/guide/nio/
参数表如下:
名称 | 类型 | 默认值 | 描述 |
use_send_queues | boolean | true | 是否对不同的连接使用不同的发送队列 |
sock_conn_timeout | int | 2000(ms) | 连接超时时间,作用于ConnectionTable |
skip_suspected_members | boolean | true | 是否要丢弃发送到suspect成员的消息 |
recv_buf_size | int | 150000 | 数据包套接字缓存大小 |
send_buf_size | int | 150000 | |
start_port | int | 7800 | 寻找可用的本地端口段,0表示没有上限 |
end_port | int | 0 |
对于TCP_NIO有如下附加参数:
名称 | 类型 | 默认值 | 描述 |
reader_threads | int | 8 | NIO读写线程数 |
writer_threads | int | 8 | |
processor_threads | int | 10 | 消息处理池的设置 |
processor_minThreads | int | 10 | |
processor_maxThreads | int | 10 | |
processor_queueSize | int | 100 | |
processor_keepAliveTime | int | -1 |
UDP,UDP_NIO
使用UDP实现的组播协议,分别使用multicast
socket和unicast
socket来实现点到多点以及点到点。
参数表如下:
名称 | 类型 | 默认值 | 描述 |
mcast_addr | String | 228.8.8.8 | 组播地址 |
mcast_port | int | 6700 | 组播端口 |
ip_mcast | boolean | true | 是否使用IP |
ip_ttl | int | 64 | 指定外发消息的TTL |
toc | int | 0 | 参见java.net.DatagramSocket#setTrafficClass 和RFC 1349 可用的值如下: IPTOS_LOWCOST (0x02) IPTOS_RELIABILITY (0x04) IPTOS_THROUGHPUT (0x08) IPTOS_LOWDELAY |
mcast_send_buf_size | int | 32000 | 指定 multicast和unicast的数据包套接字的发送和接收缓冲大小< /P> |
mcast_recv_buf_size | int | 64000 | |
ucast_send_buf_size | int | 32000 | |
ucast_recv_buf_size | int | 64000 |
TUNNEL
UDP 的替代品,使用一个连接到Router的TCP连接来代替UDP,所有外发的消息都会先发送到Router,然后再有Router来分发所有连接到此组的TUNNEL上。
此协议可以用来穿透防火墙,防火墙外的组成员使用Router连接到其的TCP连接向防火墙内发送消息。
参数表如下:
名称 | 类型 | 默认值 | 描述 |
router_port | String | 无 | router的地址 |
router_host | int | 无 | router的端口 |
No comments:
Post a Comment