Java 操作zk

一、节点操作

4 种
持久和临时
无序和有序

1.1持久化节点

public static void createPersistent() {
		if(!zkClient.exists("/java")) {
			String create = zkClient.create("/java", "java", CreateMode.PERSISTENT);
			System.out.println(create);
		}
		if(zkClient.exists("/java/io/inputstream/fileInputstream")) {
//			NoNode , 这个低估创建是自己实现的算法
			zkClient.createPersistent("/java/io/inputstream/fileInputstream", true); // 这个使用最多,它可以递归创建节点,zookeeper 原生不支持递归创建
		}
	}
	/**
	 * 创建一个持久的顺序节点
	 */
	public static void createPerSeq() {
		// zk 不支持创建同名的节点
//		/java0000000004 /java0000000005 /java0000000006
//		String create = zkClient.create("/java", "java", CreateMode.PERSISTENT_SEQUENTIAL);
		String create = zkClient.createPersistentSequential("/java", "java"); // 快捷创建节点
		System.out.println(create);
	}

1.2创建临时节点

若创建它的客户端断开连接后(和zkServer 断开),则节点会自动删除
在这里插入图片描述

/**
	 * 临时节点,若创建它的客户端断开连接,则自动死掉
	 * 使用多一点
	 */
	public static void createEm() {
		zkClient.createEphemeral("/test");
		try {
			System.out.println("挂起jvm,线程在此一致等待");
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
//		zkClient.close();
	}
	
	// 创建一个临时的顺序节点 使用少
	public static void createEmSeq() {
		
		zkClient.createEphemeralSequential("/test1", "test");
	}

1.3订阅子节点的改变(重要)

在这里插入图片描述

/**
	 * 订阅节点的改变(重要)
	 */
	public static void subScribe() {
		zkClient.subscribeChildChanges("/com.sxt.AddService", new IZkChildListener() {
			
			/**
			 * 若该父节点的字节有变化,则会执行该方法
			 */
			@Override
			public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
				System.out.println(parentPath+",下的字节点有变化");
				System.out.println("当前最新的子节点为"+currentChilds);
			}
		});
		System.out.println("开始监听");
		try {
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

1.4其他的订阅操作

public static void otherSub() {
//		zkClient.subscribeStateChanges(new IZkStateListener() {
//
//			@Override
//			public void handleStateChanged(KeeperState state) throws Exception {
//            System.out.println("当前状态为"+state);
//			}
//
//			@Override
//			public void handleSessionEstablishmentError(Throwable error) throws Exception {
//              System.out.println("写数据的异常"+error); // 写数据和时有异常会监听到
//			}
//
//			@Override
//			public void handleNewSession() throws Exception {
//                System.out.println("新连接"); // 触发条件是在一个客户端里面
//			}
//		});// 订阅服务器的状态改变(zkServer状态的改变,服务器死机了,启动)
		zkClient.subscribeDataChanges("/java", new IZkDataListener() { // 该监听针对的是自己(客户端)内部数据改变
			
			@Override
			public void handleDataDeleted(String dataPath) throws Exception {
				System.out.println(dataPath);
			}
			
			@Override
			public void handleDataChange(String dataPath, Object data) throws Exception {
				System.out.println(dataPath+":::"+data);
			}
		}); // 订阅节点数据改变的通知
         System.out.println("开始监听");
		try {
			System.in.read();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

1.5修改节点的数据

/**
	 * 给节点写数据
	 */
	public static void changeData() {
		zkClient.writeData("/java", "23456");
	}

二、注册中心

2.1 服务提供者启动->注册自己

在这里插入图片描述

2.2 服务消费者调用->获取服务列表

在这里插入图片描述

2.3 性能问题

在这里插入图片描述
服务消费者每次调用时,都有从zk 上获取一次数据

在高并发调用,每次去获取远程的服务列表,是个性能问题
若每次拉取服务要2 s -0s
远程需要1 s
=3s->1s

2.4 缓存的思想


在这里插入图片描述
查询数据:管理员的菜单

2.4 缓存的脏读

缓存里面的时间和数据源里面的数据不一致导致
Eg: 现在有个服务挂了,zk 上会自动删除它,但是缓存列表里面还有它

若:zk 上节点有变化,能修改我的缓存(订阅的功能)

/**
	 * 1 第一次从zk 上面拉取 ?
	 * 2 拉取之后保存起来
	 * 3 以后的获取数据都从缓存里面找 
	 * 
	 * @param serverName
	 * @return
	 */
	public static List<String>fetchServerListCache(String serverName){
		if(serverList.containsKey(serverName)) { // 代表之前获取过该服务的列表
			System.out.println("从缓存里面获取");
			List<String> list = serverList.get(serverName);
			return list;
		}
		List<String> fetchServerList = fetchServerList(serverName); //不包含,说明之前没有拉取过,我先拉取到,保存起来
		serverList.put(serverName, fetchServerList);
		// 拉取成功后,我开始关注这个节点,若该节点有变化,我修改缓存里面的数据
		zkClient.subscribeChildChanges("/"+serverName, new IZkChildListener() {
			
			@Override
			public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
				System.out.println("有服务死机或上线,需要更新服务的列表");
				System.out.println("缓存里面的服务列表为"+serverList.get(serverName));
				System.out.println("最新的为"+currentChilds);
				System.out.println("开始更新");
				serverList.put(serverName, currentChilds);
				System.out.println("修改成功");
				
				
			}
		});
		return fetchServerList;
	}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章