Bermula dengan Java dan Zookeeper

1. Gambaran keseluruhan

Apache ZooKeeper adalah perkhidmatan koordinasi terdistribusi yang memudahkan pengembangan aplikasi diedarkan. Ia digunakan oleh projek seperti Apache Hadoop, HBase dan lain-lain untuk kes penggunaan yang berbeza seperti pemilihan pemimpin, pengurusan konfigurasi, koordinasi nod, pengurusan sewa pelayan, dll.

Nod dalam kluster ZooKeeper menyimpan data mereka di ruang nama hierarki bersama yang serupa dengan sistem fail standard atau struktur data pokok.

Dalam artikel ini, kita akan meneroka cara menggunakan API Java Apache Zookeeper untuk menyimpan, mengemas kini dan menghapus maklumat yang disimpan di dalam ZooKeeper.

2. Persediaan

Versi terbaru perpustakaan Java Apache ZooKeeper boleh didapati di sini:

 org.apache.zookeeper zookeeper 3.4.11 

3. Model Data ZooKeeper - ZNode

ZooKeeper mempunyai ruang nama hierarki, seperti sistem fail diedarkan di mana ia menyimpan data koordinasi seperti maklumat status, maklumat koordinasi, maklumat lokasi, dan lain-lain. Maklumat ini disimpan pada nod yang berbeza.

Setiap simpul di pokok ZooKeeper disebut sebagai ZNode.

Setiap ZNode mengekalkan nombor versi dan cap waktu untuk sebarang data atau perubahan ACL. Ini juga membolehkan ZooKeeper mengesahkan cache dan menyelaraskan kemas kini.

4. Pemasangan

4.1. Pemasangan

Keluaran ZooKeeper terkini boleh dimuat turun dari sini. Sebelum melakukan itu, kita perlu memastikan bahawa kita memenuhi keperluan sistem yang dinyatakan di sini.

4.2. Mod Berdiri

Untuk artikel ini, kami akan menjalankan ZooKeeper dalam mod mandiri kerana memerlukan konfigurasi minimum. Ikuti langkah-langkah yang dijelaskan dalam dokumentasi di sini.

Catatan: Dalam mod mandiri, tidak ada replikasi jadi jika proses ZooKeeper gagal, perkhidmatan akan turun.

5. Contoh ZooKeeper CLI

Kami sekarang akan menggunakan ZooKeeper Command Line Interface (CLI) untuk berinteraksi dengan ZooKeeper:

bin/zkCli.sh -server 127.0.0.1:2181

Perintah di atas memulakan contoh mandiri secara tempatan. Sekarang mari kita lihat cara membuat ZNode dan menyimpan maklumat dalam ZooKeeper:

[zk: localhost:2181(CONNECTED) 0] create /MyFirstZNode ZNodeVal Created /FirstZnode

Kami baru sahaja membuat ZNode 'MyFirstZNode' pada akar ruang nama hierarki ZooKeeper dan menulis 'ZNodeVal' kepadanya.

Oleh kerana kami tidak melewati bendera, ZNode yang dibuat akan berterusan.

Sekarang mari kita mengeluarkan perintah 'get' untuk mengambil data serta metadata yang dikaitkan dengan ZNode:

[zk: localhost:2181(CONNECTED) 1] get /FirstZnode “Myfirstzookeeper-app” cZxid = 0x7f ctime = Sun Feb 18 16:15:47 IST 2018 mZxid = 0x7f mtime = Sun Feb 18 16:15:47 IST 2018 pZxid = 0x7f cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 22 numChildren = 0

Kita boleh mengemas kini data ZNode yang ada menggunakan operasi set .

Sebagai contoh:

set /MyFirstZNode ZNodeValUpdated

Ini akan mengemas kini data di MyFirstZNode dari ZNodeVal ke ZNodeValUpdated.

6. Contoh API ZooKeeper Java

Sekarang mari kita lihat Zookeeper Java API dan buat node, kemas kini node dan ambil beberapa data.

6.1. Pakej Java

Pengikatan ZooKeeper Java terdiri terutamanya dari dua pakej Java:

  1. org.apache.zookeeper : yang menentukan kelas utama perpustakaan pelanggan ZooKeeper bersama dengan banyak definisi statik jenis dan keadaan acara ZooKeeper
  2. org.apache.zookeeper.data : yang menentukan ciri-ciri yang berkaitan dengan ZNodes, seperti Daftar Kawalan Akses (ACL), ID, statistik, dan sebagainya

Terdapat juga API Java ZooKeeper yang digunakan dalam pelaksanaan pelayan seperti org.apache.zookeeper.server , org.apache.zookeeper.server.quorum , dan org.apache.zookeeper.server.upgrade .

Namun, mereka berada di luar ruang lingkup artikel ini.

6.2. Menyambung ke ZooKeeper Instance

Sekarang mari kita buat kelas ZKConnection yang akan digunakan untuk menyambung dan memutuskan sambungan dari ZooKeeper yang sudah berjalan:

public class ZKConnection { private ZooKeeper zoo; CountDownLatch connectionLatch = new CountDownLatch(1); // ... public ZooKeeper connect(String host) throws IOException, InterruptedException { zoo = new ZooKeeper(host, 2000, new Watcher() { public void process(WatchedEvent we) { if (we.getState() == KeeperState.SyncConnected) { connectionLatch.countDown(); } } }); connectionLatch.await(); return zoo; } public void close() throws InterruptedException { zoo.close(); } }

Untuk menggunakan perkhidmatan ZooKeeper, aplikasi harus terlebih dahulu menunjukkan objek kelas ZooKeeper , yang merupakan kelas utama perpustakaan pelanggan ZooKeeper .

In connect method, we're instantiating an instance of ZooKeeper class. Also, we've registered a callback method to process the WatchedEvent from ZooKeeper for connection acceptance and accordingly finish the connect method using countdown method of CountDownLatch.

Once a connection to a server is established, a session ID gets assigned to the client. To keep the session valid, the client should periodically send heartbeats to the server.

The client application can call ZooKeeper APIs as long as its session ID remains valid.

6.3. Client Operations

We'll now create a ZKManager interface which exposes different operations like creating a ZNode and saving some data, fetching and updating the ZNode Data:

public interface ZKManager { public void create(String path, byte[] data) throws KeeperException, InterruptedException; public Object getZNodeData(String path, boolean watchFlag); public void update(String path, byte[] data) throws KeeperException, InterruptedException; }

Let's now look at the implementation of the above interface:

public class ZKManagerImpl implements ZKManager { private static ZooKeeper zkeeper; private static ZKConnection zkConnection; public ZKManagerImpl() { initialize(); } private void initialize() { zkConnection = new ZKConnection(); zkeeper = zkConnection.connect("localhost"); } public void closeConnection() { zkConnection.close(); } public void create(String path, byte[] data) throws KeeperException, InterruptedException { zkeeper.create( path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } public Object getZNodeData(String path, boolean watchFlag) throws KeeperException, InterruptedException { byte[] b = null; b = zkeeper.getData(path, null, null); return new String(b, "UTF-8"); } public void update(String path, byte[] data) throws KeeperException, InterruptedException { int version = zkeeper.exists(path, true).getVersion(); zkeeper.setData(path, data, version); } }

In the above code, connect and disconnect calls are delegated to the earlier created ZKConnection class. Our create method is used to create a ZNode at given path from the byte array data. For demonstration purpose only, we've kept ACL completely open.

Once created, the ZNode is persistent and doesn't get deleted when the client disconnects.

The logic to fetch ZNode data from ZooKeeper in our getZNodeData method is quite straightforward. Finally, with the update method, we're checking the presence of ZNode on given path and fetching it if it exists.

Beyond that, for updating the data, we first check for ZNode existence and get the current version. Then, we invoke the setData method with the path of ZNode, data and current version as parameters. ZooKeeper will update the data only if the passed version matches with the latest version.

7. Conclusion

When developing distributed applications, Apache ZooKeeper plays a critical role as a distributed coordination service. Specifically for use cases like storing shared configuration, electing the master node, and so on.

ZooKeeper juga menyediakan API berbasis Java yang elegan untuk digunakan dalam kod aplikasi sisi pelanggan untuk komunikasi yang lancar dengan ZooKeeper ZNodes.

Dan seperti biasa, semua sumber tutorial ini boleh didapati di Github.