package com.tuling.os; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.I0Itec.zkclient.ZkClient; import java.lang.instrument.Instrumentation; import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; import java.net.InetAddress; import java.net.UnknownHostException; public class Agent { private static Agent ourInstance = new Agent(); private String server = "192.168.0.149:2181"; private ZkClient zkClient; private static final String rootPath = "/tuling-manger"; private static final String servicePath = rootPath + "/service"; private String nodePath; ///tuling-manger/service0000001 当前节点路径 private Thread stateThread; public static Agent getInstance() { return ourInstance; } private Agent() { } // javaagent 数据监控 public static void premain(String args, Instrumentation instrumentation) { Agent.getInstance().init(); } public void init() { zkClient = new ZkClient(server, 5000, 10000); System.out.println("zk连接成功" + server); // 创建根节点 buildRoot(); // 创建临时节点 createServerNode(); // 启动更新的线程 stateThread = new Thread(() -> { while (true) { updateServerNode(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } }, "zk_stateThread"); stateThread.setDaemon(true); stateThread.start(); } // 数据写到 当前的临时节点中去 public void updateServerNode() { zkClient.writeData(nodePath, getOsInfo()); } // 生成服务节点 public void createServerNode() { nodePath = zkClient.createEphemeralSequential(servicePath, getOsInfo()); System.out.println("创建节点:" + nodePath); } // 更新服务节点状态 public String getOsInfo() { OsBean bean = new OsBean(); bean.lastUpdateTime = System.currentTimeMillis(); bean.ip = getLocalIp(); bean.cpu = CPUMonitorCalc.getInstance().getProcessCpu(); MemoryUsage memoryUsag = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); bean.usedMemorySize = memoryUsag.getUsed() / 1024 / 1024; bean.usableMemorySize = memoryUsag.getMax() / 1024 / 1024; bean.pid = ManagementFactory.getRuntimeMXBean().getName(); ObjectMapper mapper = new ObjectMapper(); try { return mapper.writeValueAsString(bean); } catch (JsonProcessingException e) { throw new RuntimeException(e); } } public static String getLocalIp() { InetAddress addr = null; try { addr = InetAddress.getLocalHost(); } catch (UnknownHostException e) { throw new RuntimeException(e); } return addr.getHostAddress(); } public void buildRoot() { if (!zkClient.exists(rootPath)) { zkClient.createPersistent(rootPath); } } }
2.CPUMontior:
public class CPUMonitorCalc { private static CPUMonitorCalc instance = new CPUMonitorCalc(); private OperatingSystemMXBean osMxBean; private ThreadMXBean threadBean; private long preTime = System.nanoTime(); private long preUsedTime = 0; private CPUMonitorCalc() { osMxBean = ManagementFactory.getOperatingSystemMXBean(); threadBean = ManagementFactory.getThreadMXBean(); } public static CPUMonitorCalc getInstance() { return instance; } public double getProcessCpu() { long totalTime = 0; for (long id : threadBean.getAllThreadIds()) { totalTime += threadBean.getThreadCpuTime(id); } long curtime = System.nanoTime(); long usedTime = totalTime - preUsedTime; long totalPassedTime = curtime - preTime; preTime = curtime; preUsedTime = totalTime; return (((double) usedTime) / totalPassedTime / osMxBean.getAvailableProcessors()) * 100; } }
public class OsBean implements java.io.Serializable { public String ip; public Double cpu; public long usedMemorySize; public long usableMemorySize; public String pid; public long lastUpdateTime; public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Double getCpu() { return cpu; } public void setCpu(Double cpu) { this.cpu = cpu; } public long getUsedMemorySize() { return usedMemorySize; } public void setUsedMemorySize(long usedMemorySize) { this.usedMemorySize = usedMemorySize; } public long getUsableMemorySize() { return usableMemorySize; } public void setUsableMemorySize(long usableMemorySize) { this.usableMemorySize = usableMemorySize; } public String getPid() { return pid; } public void setPid(String pid) { this.pid = pid; } @Override public String toString() { return "OsBean{" + "ip='" + ip + '\'' + ", cpu=" + cpu + ", usedMemorySize=" + usedMemorySize + ", usableMemorySize=" + usableMemorySize + ", pid='" + pid + '\'' + ", lastUpdateTime=" + lastUpdateTime + '}'; } }
2.zooker-client:
public class AclTest { ZooKeeper zooKeeper; @Before public void init() throws IOException { zooKeeper = new ZooKeeper("192.168.0.149", 2181, event -> { System.out.println(event); }); } @Test public void getAclTest1() throws KeeperException, InterruptedException { List<ACL> acl = zooKeeper.getACL("/tuling", null); System.out.println(acl); } @Test public void setAclTest() throws KeeperException, InterruptedException { List<ACL> aclList = new ArrayList<>(); int perm = ZooDefs.Perms.ADMIN | ZooDefs.Perms.READ|ZooDefs.Perms.WRITE; aclList.add(new ACL(perm, new Id("world", "anyone"))); aclList.add(new ACL(ZooDefs.Perms.ALL, new Id("ip", "192.168.0.132"))); zooKeeper.setACL("/tuling", aclList, 5); } }
/** * @author Tommy * Created by Tommy on 2019/9/26 **/ public class ZkclientTest { ZkClient zkClient; @Before public void init() { zkClient = new ZkClient("192.168.0.149:2181", 5000, 5000); } public void createTest(){ } }
zookeeper -dubbo 实现:
public class Server { public void openServer(int port) { // 构建应用 ApplicationConfig config = new ApplicationConfig(); config.setName("simple-app"); // 通信协议 ProtocolConfig protocolConfig = new ProtocolConfig("dubbo", port); protocolConfig.setThreads(200); ServiceConfig<UserService> serviceConfig = new ServiceConfig(); serviceConfig.setApplication(config); serviceConfig.setProtocol(protocolConfig); serviceConfig.setRegistry(new RegistryConfig("zookeeper://192.168.0.149:2181")); serviceConfig.setInterface(UserService.class); UserServiceImpl ref = new UserServiceImpl(); serviceConfig.setRef(ref); //开始提供服务 开张做生意 serviceConfig.export(); System.out.println("服务已开启!端口:"+serviceConfig.getExportedUrls().get(0).getPort()); ref.setPort(serviceConfig.getExportedUrls().get(0).getPort()); } public static void main(String[] args) throws IOException { new Server().openServer(-1); System.in.read(); } }
public class UserServiceImpl implements UserService { int port; @Override public UserVo getUser(Integer id) { UserVo u = new UserVo(); u.setBirthDay(new Date()); u.setId(id); u.setPort(port); // 获取当前用户名 u.setName(ManagementFactory.getRuntimeMXBean().getName()); if (port == 20880) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } return u; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } }
3.zookper Lock:
public class ZookeeperLock { private String server = "192.168.0.149:2181"; private ZkClient zkClient; private static final String rootPath = "/tuling-lock1"; public ZookeeperLock() { zkClient = new ZkClient(server, 5000, 20000); buildRoot(); } // 构建根节点 public void buildRoot() { if (!zkClient.exists(rootPath)) { zkClient.createPersistent(rootPath); } } // 获取锁 public Lock lock(String lockId, long timeout) { // 创建临时节点 Lock lockNode = createLockNode(lockId); lockNode = tryActiveLock(lockNode);// 尝试激活锁 if (!lockNode.isActive()) { try { synchronized (lockNode) { lockNode.wait(timeout); // 线程锁住 } } catch (InterruptedException e) { throw new RuntimeException(e); } } if (!lockNode.isActive()) { throw new RuntimeException(" lock timeout"); } return lockNode; } // 释放锁 public void unlock(Lock lock) { if (lock.isActive()) { zkClient.delete(lock.getPath()); } } // 尝试激活锁 private Lock tryActiveLock(Lock lockNode) { // 获取根节点下面所有的子节点 List<String> list = zkClient.getChildren(rootPath) .stream() .sorted() .map(p -> rootPath + "/" + p) .collect(Collectors.toList()); // 判断当前是否为最小节点 String firstNodePath = list.get(0); // 最小节点是不是当前节点 if (firstNodePath.equals(lockNode.getPath())) { lockNode.setActive(true); } else { String upNodePath = list.get(list.indexOf(lockNode.getPath()) - 1); zkClient.subscribeDataChanges(upNodePath, new IZkDataListener() { @Override public void handleDataChange(String dataPath, Object data) throws Exception { } @Override public void handleDataDeleted(String dataPath) throws Exception { // 事件处理 与心跳 在同一个线程,如果Debug时占用太多时间,将导致本节点被删除,从而影响锁逻辑。 System.out.println("节点删除:" + dataPath); Lock lock = tryActiveLock(lockNode); synchronized (lockNode) { if (lock.isActive()) { lockNode.notify(); // 释放了 } } zkClient.unsubscribeDataChanges(upNodePath, this); } }); } return lockNode; } public Lock createLockNode(String lockId) { String nodePath = zkClient.createEphemeralSequential(rootPath + "/" + lockId, "w"); return new Lock(lockId, nodePath); } }
public class Lock { private String lockId; private String path; private boolean active; public Lock(String lockId, String path) { this.lockId = lockId; this.path = path; } public Lock() { } public String getLockId() { return lockId; } public void setLockId(String lockId) { this.lockId = lockId; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } }:
zookpermaster:
public class MasterResolve { private String server = "192.168.0.149:2181"; private ZkClient zkClient; private static final String rootPath = "/tuling-master"; private static final String servicePath = rootPath + "/service"; private String nodePath; private volatile boolean master = false; private static MasterResolve resolve; private MasterResolve() { zkClient = new ZkClient(server, 2000, 5000); buildRoot(); createServerNode(); } public static MasterResolve getInstance() { if (resolve == null) { resolve= new MasterResolve(); } return resolve; } // 构建根节点 public void buildRoot() { if (!zkClient.exists(rootPath)) { zkClient.createPersistent(rootPath); } } // 创建server节点 public void createServerNode() { nodePath = zkClient.createEphemeralSequential(servicePath, "slave"); System.out.println("创建service节点:" + nodePath); initMaster(); initListener(); } private void initMaster() { boolean existMaster = zkClient.getChildren(rootPath) .stream() .map(p -> rootPath + "/" + p) .map(p -> zkClient.readData(p)) .anyMatch(d -> "master".equals(d)); if (!existMaster) { doElection(); System.out.println("当前当选master"); } } private void initListener() { zkClient.subscribeChildChanges(rootPath, (parentPath, currentChilds) -> { doElection();// 执行选举 }); } // 执行选举 public void doElection() { Map<String, Object> childData = zkClient.getChildren(rootPath) .stream() .map(p -> rootPath + "/" + p) .collect(Collectors.toMap(p -> p, p -> zkClient.readData(p))); if (childData.containsValue("master")) { return; } childData.keySet().stream().sorted().findFirst().ifPresent(p -> { if (p.equals(nodePath)) { // 设置最小值序号为master 节点 zkClient.writeData(nodePath, "master"); master = true; System.out.println("当前当选master" + nodePath); } }); } public static boolean isMaster() { return getInstance().master; } }
三.web controller:
@SpringBootApplication public class ZookeeperWebApplication { public static void main(String[] args) { SpringApplication.run(ZookeeperWebApplication.class, args); } }
package tuling.zookeeper.web.control; import com.fasterxml.jackson.databind.ObjectMapper; import com.tuling.os.OsBean; import org.I0Itec.zkclient.IZkChildListener; import org.I0Itec.zkclient.IZkDataListener; import org.I0Itec.zkclient.ZkClient; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author Tommy * Created by Tommy on 2019/9/22 **/ @Controller public class MainControl implements InitializingBean { @Value("${zk:192.168.0.149:2181}") private String server; private ZkClient zkClient; private static final String rootPath = "/tuling-manger"; Map<String, OsBean> map = new HashMap<>(); @RequestMapping("/list") public String list(Model model) { model.addAttribute("items", getCurrentOsBeans()); return "list"; } private List<OsBean> getCurrentOsBeans() { List<OsBean> items = zkClient.getChildren(rootPath).stream() .map(p -> rootPath + "/" + p) .map(p -> convert(zkClient.readData(p))) .collect(Collectors.toList()); return items; } private OsBean convert(String json) { ObjectMapper mapper = new ObjectMapper(); try { return mapper.readValue(json, OsBean.class); } catch (IOException e) { throw new RuntimeException(e); } } @Override public void afterPropertiesSet() throws Exception { zkClient = new ZkClient(server, 5000, 10000); initSubscribeListener(); } // 初始化订阅事件 public void initSubscribeListener() { zkClient.unsubscribeAll(); // 获取所有子节点 zkClient.getChildren(rootPath) .stream() .map(p -> rootPath + "/" + p)// 得出子节点完整路径 .forEach(p -> { zkClient.subscribeDataChanges(p, new DataChanges());// 数据变更的监听 }); // 监听子节点,的变更 增加,删除 zkClient.subscribeChildChanges(rootPath, (parentPath, currentChilds) -> initSubscribeListener()); } // 子节点数据变化 private class DataChanges implements IZkDataListener { @Override public void handleDataChange(String dataPath, Object data) throws Exception { OsBean bean = convert((String) data); map.put(dataPath, bean); doFilter(bean); } @Override public void handleDataDeleted(String dataPath) throws Exception { if (map.containsKey(dataPath)) { OsBean bean = map.get(dataPath); System.err.println("服务已下线:" + bean); map.remove(dataPath); } } } // 警告过滤 private void doFilter(OsBean bean) { // cpu 超过10% 报警 if (bean.getCpu() > 10) { System.err.println("CPU 报警..." + bean.getCpu()); } } }