註冊中心
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";
}
}