java 操作zookeeper:
先贴上java连接zookeeper代码
public class zookeeperConnection {
final static CountDownLatch connectedSignal = new CountDownLatch(1);
static ZooKeeper zooKeeper = null;
// 1、连接zookeeper
public static ZooKeeper connect(String host) throws IOException, InterruptedException{
zooKeeper = new ZooKeeper(host,5000,new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
// 2、异步连接
if(watchedEvent.getState() == KeeperState.SyncConnected){
connectedSignal.countDown();
}
}
});
connectedSignal.await();
System.out.println("连接成功");
return zooKeeper;
}
public static void close() throws InterruptedException{
System.out.println("关闭成功");
zooKeeper.close();
}
public static void main(String[] args) throws IOException, InterruptedException {
zookeeperConnection.connect("192.168.44.5:2181");
zookeeperConnection.close();
}
}
java创建节点
public class IdAcl {
public static void main(String[] args) throws KeeperException {
try {
// 连接
ZooKeeper connect = zookeeperConnection.connect("127.0.0.1:2181");
// 确认id(确认目标,客户端)
Id id = new Id();
id.setScheme("ip");
// 127.0.0.1 在zookeeper里和localhost 是不一样的 因为zookeeper里面不会做dns校验
id.setId("127.0.0.1");
// 设置一段ip
id.setId("127.0.0.1/255");
// 创建acl (授权-增删改查)
ACL acl = new ACL();
acl.setId(id);
acl.setPerms(ZooDefs.Perms.ALL);
// 创建acl集合
List<ACL> list = new ArrayList<>();
list.add(acl);
// 创建节点
connect.create("/aclid","id:id".getBytes(),list, CreateMode.PERSISTENT);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
解释:ZooDefs.Ids.OPEN_ACL_UNSAFE:
OPEN_ACL_UNSAFE: 创建任何人都可以操作的节点
READ_ACL_UNSAFE: 创建任何人都可以读的节点
CREATOR_ALL_ACL: 设置了Auth的用户可以使用该ACL集合创建节点,该节点也只能被同样Auth授权的用户操作
Watcher
可以设置Watcher的方式:
1) 在ZooKeeper的构造函数中可以设置Watcher
2) 使用ZooKeeper.register(Watcher)显示的更改在构造函数中设置的默认Watcher
3) 通过某些方法的调用可以更改某个path对应节点的Watcher?
具体可以设置Watcher的方法如下所示:
1) 构造函数: state changes or node events
2) Register: 修改构造函数中指定的默认Watcher.
3) getData: triggered by sets data on the node, or deletes the node.
4) getChildren: triggered by deletes the node or creates/delete a child under the node.
5) exists: triggered by creates/delete the node or sets the data on the node.
其中构造函数阶段指定的Watcher一直有效(register方式属于该类),其余方法设置的Watcher仅有效一次。在方法调用时,如果指 定开启watcher,如果该节点通过getData、getChildren和exists设置了Watcher,就触发该Watcher,然后使得该 Watcher失效(但默认的Watcher还一直生效),否则触发构造函数中设定的默认Watcher。
二、zookeeper-权限(ACL)
ACL用于控制Znode的访问,和Unix文件访问权限类似,提供对某类用户设置某种权限的能力(如Unix中对Owner提供读、写、执行的权限), 但是在ZooKeeper中没有Owner、Group等概念,于是在ZooKeeper中使用ID表示某一类用户,可以对ID设置某种权限。 (ZooKeeper对ID的数量没有限制,不像Unix文件仅支持三种类型用户)
ACL 权限控制,使用:scheme:id:perm 来标识,主要涵盖 3 个方面:
权限模式(Scheme):授权的策略(客户端有很多类型(1、ip,2、用户名:密码,3、world:anyone))
授权对象(ID):授权的对象(就是客户端)
权限(Permission):授予的权限(crwda)
其特性如下:
ZooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限
每个znode支持设置多种权限控制方案和多个权限
子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点
Id id = new Id();
id.setId("1");
// digest 是加密解密作用,如果想设置ip 里面直接写成ip就可以了
id.setScheme("digest");
ACL acl = new ACL();
acl.setId(id);
// 权限: 所有,增删改 ZooDefs.Perms.CREATE; ZooDefs.Perms.DELETE (CREATE、READ、WRITE、DELETE、ADMIN )
acl.setPerms(ZooDefs.Perms.ALL);
byte[] data = "localhots:8099".getBytes();
List<ACL> acls = new ArrayList<>();
acls.add(acl);
// 创建 ZooDefs.Ids.OPEN_ACL_UNSAFE 权限 PERSISTENT_SEQUENTIAL 持久化节点- 顺序 ,临时节点(EPHEMERAL),顺序节点(SEQUENTIAL)
zooKeeper.create("/alomsc",data, acls, CreateMode.PERSISTENT_SEQUENTIAL);
// zooKeeper.create("/alomsc",data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
1. scheme 采用何种方式授权
**world:**默认方式,相当于全部都能访问
**auth**:代表已经认证通过的用户(cli中可以通过addauth digest user:pwd 来添加当前上下文中的授权用户)
**digest**:即用户名:密码这种方式认证,这也是业务系统中最常用的。用 *username:password* 字符串来产生一个MD5串,然后该串被用来作为ACL ID。认证是通过明文发送*username:password* 来进行的,当用在ACL时,表达式为*username:base64* ,base64是password的SHA1摘要的编码。
**ip**:使用客户端的主机IP作为ACL ID 。这个ACL表达式的格式为*addr/bits* ,此时addr中的有效位与客户端addr中的有效位进行比对。
2. ID 给谁授予权限
授权对象ID是指,权限赋予的用户或者一个实体,例如:IP 地址或者机器。授权模式 schema 与 授权对象 ID 之间
3. permission 授予什么权限
**CREATE、READ、WRITE、DELETE、ADMIN** 也就是 **增、删、改、查、管理**权限,这5种权限简写为crwda
这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限
**更详细的如下:
**CREATE** c 可以创建子节点
**DELETE** d 可以删除子节点(仅下一级节点)
**READ** r 可以读取节点数据及显示子节点列表
**WRITE** w 可以设置节点数据
**ADMIN** a 可以设置节点访问控制列表权限
给节点赋权限(ip)
//授权
zooKeeper.addAuthInfo("ip", "127.0.0.1".getBytes());
// // 获取版本
Stat stat = zooKeeper.exists(path, true);
// int version = stat.getVersion();
// System.out.println(version);
//
// 设置ip权限
// Id id = new Id();
// 127.0.0.1 在zookeeper里面和localhost是不一样的 ,zookeeper不会dns解析
// id.setScheme("ip");
// id.setId("192.168.44.1");
//
// // 2、创建权限对象
// ACL aclM = new ACL();
// aclM.setId(id);
// aclM.setPerms(Perms.ALL);
//
// // 3、添加到集合
// List<ACL> acls = new ArrayList<ACL>();
// acls.add(aclM);
//
// // 打印权限列表
// zooKeeper.setACL(path, acls, zooKeeper.exists(path, true).getAversion());
List<ACL> acl = zooKeeper.getACL(path, stat);
System.out.println(acl.toString());
System.out.println("设置权限成功");
linux 命令:
setAcl /test2 ip:127.0.0.1:crwda #修改此IP具有所有权限
setAcl /test1 world:anyone:acd #修改为所有人可以acd
addauth digest user:111222 #增加授权用户,明文用户名和密码
setAcl /test digest:用户名:密码:权限 加密后用户和密码 (eg:
setAcl /test digest: user:BBO7K8dPkoek
)
[zk: localhost:2181(CONNECTED) 44] create /t4 44
Created /t4
[zk: localhost:2181(CONNECTED) 45] addauth digest qlq:111222 #增加授权用户,明文用户名和密码
[zk: localhost:2181(CONNECTED) 46] setAcl /t4 auth:qlq:cdwra #授予权限
cZxid = 0x40000001d
ctime = Tue Mar 12 15:16:56 CST 2019
mZxid = 0x40000001d
mtime = Tue Mar 12 15:16:56 CST 2019
pZxid = 0x40000001d
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
[zk: localhost:2181(CONNECTED) 48] getAcl /t4
'digest,'qlq:JWNEexxIoeVompjU7O5pZzTU+VQ=
: cdrwa
设置超级用户
/**
* 生成超级用户
* @param usernameAndPassword
* SERVER_JVMFLAGS="-Dzookeeper.DigestAuthenticationProvider.superDigest=super:BBO7K8dPkoek/JxIHqXxM75QRpI= $SERVER_JVMFLAGS"
* @return
*/
private static String superEncode(String usernameAndPassword){
try {
String generateDigest = DigestAuthenticationProvider.generateDigest(usernameAndPassword);
return generateDigest;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return "";
}
public static void main(String[] args) {
// 用户名:super 密码:123456
System.out.println(superEncode("super:123456"));
}
linux 命令:
进入到zk的客户端目录级
输入: vim ./zkEnv.sh
将原来的超级用户换成新生成的用户 ;标红的为用户的生成的密码
SERVER_JVMFLAGS="-Dzookeeper.DigestAuthenticationProvider.superDigest=super:BBO7K8dPkoek/JxIHqXxM75QRpI= $SERVER_JVMFLAGS"
更换完成重启zookeeper服务
./zkServer.sh restart
注:超级管理员可以与多个,但是建议最好不要建多个超级管理员