Memulai Java dan Zookeeper

1. Ikhtisar

Apache ZooKeeper adalah layanan koordinasi terdistribusi yang memudahkan pengembangan aplikasi terdistribusi. Ini digunakan oleh proyek seperti Apache Hadoop, HBase, dan lainnya untuk kasus penggunaan yang berbeda seperti pemilihan pemimpin, manajemen konfigurasi, koordinasi node, manajemen sewa server, dll.

Node dalam klaster Zookeeper menyimpan data mereka dalam namespace hierarki bersama yang mirip dengan sistem file standar atau struktur data pohon.

Pada artikel ini, kita akan mempelajari cara menggunakan Java API Apache Zookeeper untuk menyimpan, memperbarui, dan menghapus informasi yang disimpan dalam Zookeeper.

2. Penyiapan

Versi terbaru pustaka Java Apache ZooKeeper dapat ditemukan di sini:

 org.apache.zookeeper zookeeper 3.4.11 

3. Model Data ZooKeeper - ZNode

Zookeeper memiliki namespace hierarki, seperti sistem file terdistribusi di mana ia menyimpan data koordinasi seperti informasi status, informasi koordinasi, informasi lokasi, dll. Informasi ini disimpan di node yang berbeda.

Setiap node di pohon ZooKeeper disebut sebagai ZNode.

Setiap ZNode menyimpan nomor versi dan cap waktu untuk data apa pun atau perubahan ACL. Selain itu, ini memungkinkan Zookeeper memvalidasi cache dan mengoordinasikan pembaruan.

4. Instalasi

4.1. Instalasi

Rilis ZooKeeper terbaru dapat diunduh dari sini. Sebelum melakukan itu, kami perlu memastikan bahwa kami memenuhi persyaratan sistem yang dijelaskan di sini.

4.2. Mode Mandiri

Untuk artikel ini, kami akan menjalankan Zookeeper dalam mode mandiri karena memerlukan konfigurasi minimal. Ikuti langkah-langkah yang dijelaskan dalam dokumentasi di sini.

Catatan: Dalam mode mandiri, tidak ada replikasi jadi jika proses Zookeeper gagal, layanan akan turun.

5. Contoh CLI ZooKeeper

Kami sekarang akan menggunakan Antarmuka Baris Perintah (CLI) ZooKeeper untuk berinteraksi dengan ZooKeeper:

bin/zkCli.sh -server 127.0.0.1:2181

Perintah di atas memulai instance mandiri secara lokal. Sekarang mari kita lihat cara membuat ZNode dan menyimpan informasi dalam ZooKeeper:

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

Kami baru saja membuat ZNode 'MyFirstZNode' di root namespace hierarki ZooKeeper dan menulis 'ZNodeVal' padanya.

Karena kita belum memberikan flag apa pun, ZNode yang dibuat akan tetap ada.

Sekarang mari kita berikan perintah 'get' untuk mengambil data serta metadata yang terkait 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

Kami dapat memperbarui data ZNode yang ada menggunakan operasi yang ditetapkan .

Sebagai contoh:

set /MyFirstZNode ZNodeValUpdated

Ini akan memperbarui data di MyFirstZNode dari ZNodeVal ke ZNodeValUpdated.

6. Contoh Zookeeper Java API

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

6.1. Paket Java

Binding ZooKeeper Java sebagian besar terdiri dari dua paket Java:

  1. org.apache.zookeeper : yang mendefinisikan kelas utama pustaka klien Zookeeper bersama dengan banyak definisi statis dari jenis dan status peristiwa Zookeeper
  2. org.apache.zookeeper.data : yang mendefinisikan karakteristik yang terkait dengan ZNodes, seperti Daftar Kontrol Akses (ACL), ID, statistik, dan sebagainya

Ada juga API Java ZooKeeper yang digunakan dalam implementasi server seperti org.apache.zookeeper.server , org.apache.zookeeper.server.quorum , dan org.apache.zookeeper.server.upgrade .

Namun, mereka berada di luar cakupan artikel ini.

6.2. Menghubungkan ke Instance ZooKeeper

Sekarang mari buat kelas ZKConnection yang akan digunakan untuk menghubungkan 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 layanan Zookeeper, aplikasi harus terlebih dahulu membuat instance objek kelas Zookeeper , yang merupakan kelas utama pustaka klien 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 kode aplikasi sisi klien untuk komunikasi yang lancar dengan ZNodes ZooKeeper.

Dan seperti biasa, semua sumber untuk tutorial ini dapat ditemukan di Github.