Group Member
组成员管理。
将此实例添加到一个组中,并对组内成员缓存进行维护。
1. 关键 API
org.apache.curator.framework.recipes.nodes.GroupMember
org.apache.curator.framework.recipes.nodes.PersistentNode
org.apache.curator.framework.recipes.cache.PathChildrenCache
2. 机制说明
有关PersistentNode
的介绍,可以参见
有关PathChildrenCache
的介绍,可以参见
GroupMember本质上就是将PersistentEphemeralNode与PathChildrenCache的组合起来使用。
3. 用法
3.1 创建
public GroupMember(CuratorFramework client, String membershipPath, String thisId, byte[] payload)
- thisId
- 组成员的ID标识符
- 对与同一个组内的成员,其ID必须唯一
- payload
- 组成员的数据
- 写入组成员节点的数据
3.2 使用
GroupMember在使用前必须调用group.start();
,而在使用完成后,则需要调用group.close();
。 close()
会使得当前实例从组中移除
可以调用group.getCurrentMembers();
查看成员信息。
4. 错误处理
GroupMember实例内部会处理所有的错误,并在需要时重新创建节点。
5. 源码分析
5.1 类定义
public class GroupMember implements Closeable {}
- 实现了
java.io.Closeable
接口
5.2 成员变量
public class GroupMember implements Closeable{ private final PersistentEphemeralNode pen; private final PathChildrenCache cache; private final String thisId;}
- pen
org.apache.curator.framework.recipes.nodes.PersistentEphemeralNode
- cache
org.apache.curator.framework.recipes.cache.PathChildrenCache
- thisId
5.3 构造器
public GroupMember(CuratorFramework client, String membershipPath, String thisId){ this(client, membershipPath, thisId, CuratorFrameworkFactory.getLocalAddress());}public GroupMember(CuratorFramework client, String membershipPath, String thisId, byte[] payload){ this.thisId = Preconditions.checkNotNull(thisId, "thisId cannot be null"); cache = newPathChildrenCache(client, membershipPath); pen = newPersistentEphemeralNode(client, membershipPath, thisId, payload);}protected PathChildrenCache newPathChildrenCache(CuratorFramework client, String membershipPath){ return new PathChildrenCache(client, membershipPath, true);}protected PersistentEphemeralNode newPersistentEphemeralNode(CuratorFramework client, String membershipPath, String thisId, byte[] payload){ return new PersistentEphemeralNode(client, PersistentEphemeralNode.Mode.EPHEMERAL, ZKPaths.makePath(membershipPath, thisId), payload);}
- 主要是对
PersistentEphemeralNode
和PathChildrenCache
的初始化 - 默认的成员节点数据是本机IP地址
- 创建的节点为临时节点
- 会创建临时节点:
membershipPath/thisId
- 所以thisId在组内必须唯一
- 会创建临时节点:
5.4 启动
GroupMember在使用前,必须调用start()
启动。
public void start(){ pen.start(); try { cache.start(); } catch ( Exception e ) { ThreadUtils.checkInterrupted(e); Throwables.propagate(e); }}
- 先通过
PersistentEphemeralNode
创建节点 - 然后调用
PathChildrenCache
获取节点数据并缓存
5.5 关闭
GroupMember在使用完之后,必须调用close()
关闭。
public void close() { CloseableUtils.closeQuietly(cache); CloseableUtils.closeQuietly(pen); }
与启动时的顺序正相反:
- 先关闭节点数据缓存
- 再关闭节点
5.6 获取组内成员
可以调用public Map<String,byte[]> getCurrentMembers()
方法获取组内成员的信息。
- 返回Map以成员ID为key
- 以成员的数据(
payload
)为value
public MapgetCurrentMembers(){ ImmutableMap.Builder builder = ImmutableMap.builder(); boolean thisIdAdded = false; for ( ChildData data : cache.getCurrentData() ) { String id = idFromPath(data.getPath()); thisIdAdded = thisIdAdded || id.equals(thisId); builder.put(id, data.getData()); } if ( !thisIdAdded ) { builder.put(thisId, pen.getData()); // this instance is always a member } return builder.build();}
- 如果节点中已经有thisId了,则会使用自身数据进行覆盖
- 所以thisId不要重复
6. 小结
从某种意义上来说,GroupMember就是一个分布式的Map。
通过GroupMember可以方便的应用于分布式多个节点的简单管理。
但是其对thisId的重复性没有做什么严格的管理,所以在使用时需要注意。 thisId不论重复,实例自身都认为自己一定在组中
其使用临时节点,所以在节点意外退出时,其他组员可以通过getCurrentMembers()
发现。 这样可以通过GroupMember
进行,多节点的调度场景的应用。