preface
This article mainly explains the classic usage scenarios of Zookeeper, the use of Zookeeper native client and Apache cursor open source client, and the configuration of Zookeeper cluster.
Zookeeper mainly includes:
- Distributed configuration center
- Distributed registry
- Distributed lock
- Distributed queue
- Cluster election
- Distributed barrier
- Publish / subscribe
1, Java client for Zookeeper
1. Use of zookeeper distributed configuration center
The principle of configuration center is to monitor a node. As long as the node changes, it will notify the client to obtain the changed data.
effect:
I posted my pom file directly. In fact, I only need a zookeeper. The rest are supplementary items.
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.5</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--introduce zookeeper--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.3</version> </dependency> <!--introduce lombok Convenient processing class--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--introduce Junit test--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <!--introduce Jackson Used to serialize classes--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!--springboot-test My bag--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies>
Create a configuration class:
@Data //Note: on the class, the get, set, equals, hashCode, canEqual, toString methods of the class are provided @NoArgsConstructor //Note: on a class, provide a parameterless structure of the class public class MyConfig { private String key; private String name; }
Create Zookeeper client (the code that feels difficult to understand is annotated)
@Slf4j public class ZookeeperClient { @Test public void test01() throws IOException, InterruptedException, KeeperException { final String CONNECT_STRING = "10.10.2.21:2181"; final int SESSION_TIME_OUT = 30*1000; /* Countdown counter: a synchronization tool class between multiple threads. It is mainly used to control thread waiting, which can make a thread wait until countdown Finish and then start execution. The following main thread is countDownLatch.await(); To block the execution of the main thread. The code after the main thread will not continue to execute until the Zookeeper thread is created */ final CountDownLatch countDownLatch = new CountDownLatch(1); final ZooKeeper zooKeeper = new ZooKeeper(CONNECT_STRING, SESSION_TIME_OUT, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { if(watchedEvent.getType() == (Event.EventType.None) && watchedEvent.getState() == Event.KeeperState.SyncConnected){ log.info("Connection established"); countDownLatch.countDown();//Decrements the number of locks and releases all waiting threads when the count reaches zero } } }); /** * Why CountDownLatch? Because the Zookeeper client is an asynchronous thread and a daemon thread * (this.createConnection()Two threads new ClientCnxn.SendThread() and new ClientCnxn.EventThread() are in the method * Click in and you will find that all the threads are daemon threads this.setDaemon(true);) * This means that when the main thread ends, the zookeeper thread will also end. At this time, zookeeper may not be linked successfully */ countDownLatch.await();//Blocks the current thread until the counter value is zero. final MyConfig myConfig = new MyConfig(); myConfig.setKey("anyKey"); myConfig.setName("anyName"); //The jackson serialization tool class is used final ObjectMapper objectMapper = new ObjectMapper(); final byte[] bytes = objectMapper.writeValueAsBytes(myConfig); //Create node final String s = zooKeeper.create("/myconfig", bytes, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); //This watcher is proposed because zookeeper listens to nodes once. If you want to realize circular listening, you need to call it circularly. That is, in the watcher, zooKeeper.getData() final Watcher watcher = new Watcher() { @SneakyThrows @Override public void process(WatchedEvent event) { log.info("......."); if(event.getType() == Event.EventType.NodeDataChanged && event.getPath() != null && event.getPath().equals("/myconfig")){ log.info("path:{}Has changed",event.getPath()); final byte[] data = zooKeeper.getData("/myconfig", this, null); final MyConfig newConfig = objectMapper.readValue(new String(data), MyConfig.class); log.info("Data changes:{}",newConfig); } } }; //Get data and create listener byte[] data = zooKeeper.getData("/myconfig", watcher, null);//If you don't need to listen for node changes, just copy the watcher to null final MyConfig originalMyConfig = objectMapper.readValue(new String(data), MyConfig.class); log.info("raw data:{}",originalMyConfig); //The reason to sleep all the time is that the thread of the zookeeper client is a daemon thread, so when the main thread ends, the zookeeper client will end. Therefore, in order to ensure that the client can always connect to the server, the main thread must sleep all the time TimeUnit.SECONDS.sleep(Integer.MAX_VALUE); } }
Detailed explanation of main parameters in Zookeeper instantiation methods:
There are comments on the corresponding construction method for the meaning of each parameter
For example: connectString
2. Use of zookeeper's Java API
Use an abstract class to create a Zookeeper connection
This is the method of getData, which is used to obtain the data of the specified node.
The setData method is used to set node data
2, Using the cursor client
Add maven corresponding to curator receipts to the pom file.
Then the main code for connecting zookeeper is
1. Create node
< < 1: > > create node recursively
< < 2: > > create node in protection mode
3, Zookeeper cluster mode
concept
Zookeeper cluster mode has three different types of roles;
Leader: handles all transaction requests (write requests) and read requests. There can only be one leader in the cluster
Follower: it can only process read requests and act as a candidate node for the Leader. That is, if the Leader goes down, the follower node will participate in the salary Leader election, which may be called the salary Leader node.
Observer: only read requests can be processed. Can't participate in the election.
Cluster construction
At present, build a pseudo cluster:
Step 1: first configure the transaction data storage path. The number in each myid represents the ID corresponding to its service
Step 2:
Configure the corresponding configuration file
The first port 2001 is the port for communication between the Leader and Follower nodes
The second port 3001 is required for cluster election
A total of four services are configured, and the fourth is configured as an Observer node
Step 3 start the service: