大數據教程(3.8):zookeeper的java客戶端API簡介及監聽原理

    以前章節介紹了zookeeper集羣的自動化啓動腳本,本節博主將帶你們簡單的使用zookeeper的java客戶端API,從而瞭解其使用。java

    zookeeper監聽器原理:node

   zookeeper使用步驟:linux

(1)新建maven項目em-zookeeper-testapache

(2)解壓以前在linux系統中安裝集羣的zookeeper安裝包到E:\zookeeper-3.4.13\,打開E:\zookeeper-3.4.13\dist-maven目錄查看pom文件centos

(3)按照以上信息在em-zookeeper-test項目的pom中加入zookeeper服務器/客戶端(目前客戶端和服務端是合在一塊兒的)依賴。服務器

pom.xmlsession

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.empire.zookeeper.test</groupId>
	<artifactId>em-zookeeper</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>em-zookeeper</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
		</dependency>
		<dependency>
			<groupId>org.apache.zookeeper</groupId>
			<artifactId>zookeeper</artifactId>
			<version>3.4.13</version>
		</dependency>

	</dependencies>
	   <build>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.21.0</version>
                <inherited>true</inherited>
                <configuration>
                    <!-- <skip>true</skip> -->
                    <forkMode>once</forkMode>  
                    <argLine>-Dfile.encoding=UTF-8</argLine>   
                </configuration>
            </plugin>
            <!-- 拷貝依賴的jar包到lib目錄 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <!-- ${project.build.directory} 構建目錄,缺省爲target -->
                            <outputDirectory>
                                ${project.build.directory}/lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
           <!--  <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <archive>
                        <manifest>
                            <mainClass></mainClass>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                    </archive>
                    <classesDirectory>
                    </classesDirectory>
                </configuration>
            </plugin> -->
        </plugins>
    </build>
</project>

(4)zookeeperzookeeper的java客戶端API使用案例app

package com.empire.zookeeper.test.em_zookeeper;

import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

public class SimpleZkClient {

	private static final String connectString = "centos-aaron-07:2181,centos-aaron-08:2181,centos-aaron-16:2181";
	private static final int sessionTimeout = 1000;

	private CountDownLatch connectedSemaphore = new CountDownLatch(1); 
	ZooKeeper zkClient = null;

	@Before
	public void init() throws Exception {
		
		zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
			public void process(WatchedEvent event) {
				// 收到事件通知後的回調函數(應該是咱們本身的事件處理邏輯)
				System.out.println(event.getType() + "---" + event.getPath());
				try {
					zkClient.getChildren("/", true);
					//Decrements the count of the latch, releasing all waiting threads if the count reaches zero.
					connectedSemaphore.countDown(); 
				} catch (Exception e) {
				}
			}
		});
		//Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted. 
		connectedSemaphore.await();
		//Thread.currentThread().sleep(10000);

	}

	/**
	 * 數據的增刪改查
	 * 
	 * @throws InterruptedException
	 * @throws KeeperException
	 */

	// 建立數據節點到zk中
	@Test
	public void testCreate() throws KeeperException, InterruptedException {
		// 參數1:要建立的節點的路徑 參數2:節點大數據 參數3:節點的權限 參數4:節點的類型
		String nodeCreated = zkClient.create("/eclipse", "hellozk".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		//上傳的數據能夠是任何類型,但都要轉成byte[]
	}

	//判斷znode是否存在
	@Test	
	public void testExist() throws Exception{
		Stat stat = zkClient.exists("/eclipse", false);
		System.out.println(stat==null?"not exist":"exist");
		
		
	}
	
	// 獲取子節點
	@Test
	public void getChildren() throws Exception {
		List<String> children = zkClient.getChildren("/", true);
		for (String child : children) {
			System.out.println(child);
		}
		//Thread.sleep(Long.MAX_VALUE);
	}

	//獲取znode的數據
	@Test
	public void getData() throws Exception {
		
		byte[] data = zkClient.getData("/eclipse", false, null);
		System.out.println(new String(data));
		
	}
	
	//刪除znode
	@Test
	public void deleteZnode() throws Exception {
		
		//參數2:指定要刪除的版本,-1表示刪除全部版本
		zkClient.delete("/eclipse", -1);
		
		
	}
	//刪除znode
	@Test
	public void setData() throws Exception {
		
		zkClient.setData("/app1", "imissyou angelababy".getBytes(), -1);
		
		byte[] data = zkClient.getData("/app1", false, null);
		System.out.println(new String(data));
		
	}
	
	
}

(5)日誌配置(zookeeper須要打印日誌)less

### set log levels ###
log4j.rootLogger = debug ,  stdout ,  D ,  E

### \u8F93\u51FA\u5230\u63A7\u5236\u53F0 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{1}:%L - %m%n

### \u8F93\u51FA\u5230\u65E5\u5FD7\u6587\u4EF6 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/log.log
log4j.appender.D.Append = true
## \u8F93\u51FADEBUG\u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### \u4FDD\u5B58\u5F02\u5E38\u4FE1\u606F\u5230\u5355\u72EC\u6587\u4EF6 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
## \u5F02\u5E38\u65E5\u5FD7\u6587\u4EF6\u540D
log4j.appender.E.File = logs/error.log
log4j.appender.E.Append = true
## \u53EA\u8F93\u51FAERROR\u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7!!!
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

(6)問題思考(在沒加鎖以前很容易報錯)eclipse

org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /eclipse
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:102)
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:54)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1111)
	at org.apache.zookeeper.ZooKeeper.exists(ZooKeeper.java:1139)
	at com.empire.zookeeper.test.em_zookeeper.SimpleZkClient.testExist(SimpleZkClient.java:57)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

該問題主要時因爲zookeeper的內部實現機制產生的,由於在項目中建立zookeeper鏈接時,同時建立了connect、listener兩個線程,connet用於數據發送傳遞,而listener用於監聽zookeeper的下發通知,且listener線程是做爲connect線程的守護線程工做的。因爲zookeeper在建立鏈接時會花非不少時間以及資源,故在建立過程當中,就已經返回了鏈接對象,該鏈接對象須要在zookeeper向客戶端發送了鏈接建立成功的通知SyncConnected事件後纔可以使用,因此此處咱們能夠加一把鎖CountDownLatch來實現業務代碼暫停等待。

 

    最後寄語,以上是博主本次文章的所有內容,若是你們以爲博主的文章還不錯,請點贊;若是您對博主其它服務器技術或者博主本人感興趣,請關注博主博客,而且歡迎隨時跟博主溝通交流。

相關文章
相關標籤/搜索