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
注:超級管理員可以與多個,但是建議最好不要建多個超級管理員