基於Zookeeper實現簡單的服務註冊與訂閱

註冊中心

Zookeeper服務類:

package com.lic;
import org.apache.zookeeper.*;
import java.io.IOException;
/***
 * 註冊中心 對外提供註冊服務的
 */
public class ZookeeperServerRegistry {
    private ZooKeeper zk;
    public static final String root="/lic";  //需要手動創建根節點
    private static final String  host="192.168.2.100:2181,192.168.2.101:2181,192.168.2.102:2181";
    public ZooKeeper getConnection(Watcher watch) throws IOException {
        zk=new ZooKeeper(host,500,watch);
        return zk;
    }
}

服務節點信息類: 

用於維護註冊到zookeeper中的服務信息(IP, 端口號, 服務名稱等)

package com.lic;
import java.io.Serializable;
public class StatDto implements Serializable {
    private String ip;
    private String name;
    private String port;
    private Integer num;//連接數
    private String status;
    private String node;
    private String client;

    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPort() {
        return port;
    }
    public void setPort(String port) {
        this.port = port;
    }
    public Integer getNum() {
        return num;
    }
    public void setNum(Integer num) {
        this.num = num;
    }
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getNode() {
        return node;
    }
    public void setNode(String node) {
        this.node = node;
    }
    public String getClient() {
        return client;
    }
    public void setClient(String client) {
        this.client = client;
    }
}

服務狀態維護類:

package com.lic;
public class ServerStatus {
    //wait:無消費者,run:運行中,stop:禁用中
    public static final String run="run";
    public static final String wait="wait";
    public static final String stop="stop";
}

 


服務提供者

package com.lic;
import com.alibaba.fastjson.JSON;
import org.apache.zookeeper.*;
import java.io.IOException;
public class ProviderServers implements Watcher {
    ZookeeperServerRegistry bitZookeeperServer=new ZookeeperServerRegistry();
    /***
     * 註冊
     */
    void register(String serverName) throws IOException, KeeperException, InterruptedException {
        ZooKeeper zook= bitZookeeperServer.getConnection(this);
        //創建服務節點
        String node=  zook.create(ZookeeperServerRegistry.root+"/server",serverName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println("創建成功過"+serverName+",節點:"+node);
    }
    @Override
    public void process(WatchedEvent watchedEvent) {

    }
    public static void main(String[] args) throws InterruptedException, IOException, KeeperException {
        ProviderServers server=new ProviderServers();
        StatDto stat=new StatDto();
        int i=0;
        stat.setIp(args[i++]);  //IP
        stat.setPort(args[i++]); //端口
        stat.setName(args[i++]);  //服務名稱
        stat.setNum(0);
        stat.setStatus(ServerStatus.wait);  //服務狀態
        server.register(JSON.toJSONString(stat));
        Thread.sleep(Long.MAX_VALUE);
    }
}

服務消費者

package com.lic;
import com.alibaba.fastjson.JSON;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.SecureRandom;
import java.util.List;

/***
 * dubbo的 consumer
 */
public class ConsumerServers implements Watcher {
    Logger logger = LoggerFactory.getLogger(ConsumerServers.class);
    ZookeeperServerRegistry bitZook = new ZookeeperServerRegistry();
    private ZooKeeper zook;
    private String clientName;

    public StatDto useServer(List<String> data, int dom, int i)
            throws Exception {
        if (data.size() == i) {
            throw new Exception("沒有可用的服務");
        }
        String node = data.get(dom);
        byte[] bytes = zook.getData(ZookeeperServerRegistry.root + "/" + node,
                true, null);
        String datas = new String(bytes);
        StatDto dto = JSON.parseObject(datas, StatDto.class);
        if (ServerStatus.stop.equals(dto.getStatus())) {
            i++;
            useServer(data, dom, i);
        }
        dto.setNode(node);
        return dto;

    }

    /**
     * 客戶端訂閱
     * @param clientName
     * @throws Exception
     */
    public void subscribe(String clientName) throws Exception {
        this.clientName = clientName;
        zook = bitZook.getConnection(this);
        List<String> data = zook.getChildren(ZookeeperServerRegistry.root, true); //獲取根節點下的所有服務節點
        if (data.isEmpty()) {
            throw new Exception("沒有可用的服務");
        }
        //隨機選取一個服務
        int dom = new SecureRandom().nextInt(data.size());
        StatDto dto = useServer(data, dom, 0);
        dto.setNum(dto.getNum() + 1);
        dto.setName(dto.getName());
        dto.setClient(dto.getClient() == null ? clientName : dto.getClient() + "," + clientName);
        dto.setStatus(ServerStatus.run);
        //更新節點內容
        zook.setData(ZookeeperServerRegistry.root + "/" + dto.getNode(), JSON.toJSONString(dto).getBytes(), -1);

    }
    public void call() throws InterruptedException {
        System.out.println("客戶端開啓,建立netty連接");
    }
    @Override
    public void process(WatchedEvent event) {
        try {
            if (event.getType() == EventType.NodeChildrenChanged) {
                System.out.println("服務器發生改變,重新訂閱");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws Exception {
        ConsumerServers client = new ConsumerServers();
        client.subscribe(args[0]);
        try {
            client.call();
            Thread.sleep(Long.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

監視器

package com.lic;

import com.alibaba.fastjson.JSON;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/admin")
public class AdminController {

   ZookeeperServerRegistry bitZook = new ZookeeperServerRegistry();
   private ZooKeeper zook;

   @RequestMapping("/list")
   public String getList(HttpServletRequest request) throws Exception {
      zook = bitZook.getConnection(new Watcher() {
         @Override
         public void process(WatchedEvent event) {
         }
      });
      List<String> data = zook.getChildren(ZookeeperServerRegistry.root, true);
      List<StatDto> serverList = new ArrayList<StatDto>();
      for (String server : data) {
         byte[] bytes = zook.getData(ZookeeperServerRegistry.root + "/" + server,
               false, null);
         String datas = new String(bytes);
         StatDto dto = JSON.parseObject(datas, StatDto.class);
         serverList.add(dto);
      }
      request.setAttribute("serverList", serverList);
      return "admin";

   }

   @RequestMapping("/stop")
   public String stop(HttpServletRequest request) throws Exception {
      zook = bitZook.getConnection(new Watcher() {
         @Override
         public void process(WatchedEvent event) {
         }
      });
      String server = request.getParameter("server");
      byte[] bytes = zook.getData(ZookeeperServerRegistry.root + "/" + server,
            false, null);
      String datas = new String(bytes);
      StatDto dto = JSON.parseObject(datas, StatDto.class);
      dto.setStatus(ServerStatus.stop);
      zook.setData(ZookeeperServerRegistry.root + "/" + server,
            JSON.toJSONString(dto).getBytes(), -1);
      
      return "redirect:/admin/list";
   }
   
   @RequestMapping("/run")
   public String run(HttpServletRequest request) throws Exception {
      zook = bitZook.getConnection(new Watcher() {
         @Override
         public void process(WatchedEvent event) {
         }
      });
      String server = request.getParameter("server");
      byte[] bytes = zook.getData(ZookeeperServerRegistry.root + "/" + server,
            false, null);
      String datas = new String(bytes);
      StatDto dto = JSON.parseObject(datas, StatDto.class);
      dto.setStatus(ServerStatus.run);
      zook.setData(ZookeeperServerRegistry.root + "/" + server,
            JSON.toJSONString(dto).getBytes(), -1);
      return "redirect:/admin/list";
   }

   @RequestMapping("/delete")
   public String delete(HttpServletRequest request) throws Exception {
      zook = bitZook.getConnection(new Watcher() {
         @Override
         public void process(WatchedEvent event) {
         }
      });
      String server = request.getParameter("server");
      byte[] bytes = zook.getData(ZookeeperServerRegistry.root + "/" + server,
            false, null);
      String datas = new String(bytes);
      StatDto dto = JSON.parseObject(datas, StatDto.class);
      dto.setStatus(ServerStatus.stop);
      zook.delete(ZookeeperServerRegistry.root + "/" + server, -1);
      return "redirect:/admin/list";
   }
}

 

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