1 Ngix 和 dubbo的负载均衡的区别?
Ngix负责前端的负载均衡,zookeeper负责后台的dubbo的rpc的集群的负载均衡
2 代码实现
监听者
import java.io.IOException;
import org.apache.log4j.Logger;
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;
public class WatchMore
{
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(WatchMore.class);
// 定义常量
private static final String CONNECTSTRING = "192.168.10.167:2181";
private static final int SESSION_TIMEOUT = 50 * 1000;
private static final String PATH = "/atguigu";
// 定义实例变量
private ZooKeeper zk = null;
private String oldValue = "";
public ZooKeeper startZK() throws IOException
{
return new ZooKeeper(CONNECTSTRING, SESSION_TIMEOUT, new Watcher() {
@Override
public void process(WatchedEvent event)
{
}
});
}
public void createZNode(String nodePath, String nodeValue) throws KeeperException, InterruptedException
{
zk.create(nodePath, nodeValue.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
public String getZNode(String nodePath) throws KeeperException, InterruptedException
{
String result = "";
byte[] byteArray = zk.getData(nodePath, new Watcher() {
@Override
public void process(WatchedEvent event)
{
try {
triggerValue(nodePath);
}
catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}, new Stat());
result = new String(byteArray);
oldValue = result;
return result;
}
public boolean triggerValue(String nodePath) throws KeeperException, InterruptedException
{
String result = "";
byte[] byteArray = zk.getData(nodePath, new Watcher() {
@Override
public void process(WatchedEvent event)
{
try {
triggerValue(nodePath);
}
catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}, new Stat());
result = new String(byteArray);
String newValue = result;
if (oldValue.equals(newValue)) {
logger.info("**************no change****************");
return false;
}
else {
logger.info("**************oldValue:" + oldValue + "\t newValue: " + newValue);
oldValue = newValue;
return true;
}
}
public static void main(String[] args) throws IOException, KeeperException, InterruptedException
{
WatchMore myWatch = new WatchMore();
// 1 获得zk实例
myWatch.setZk(myWatch.startZK());
if (myWatch.getZk().exists(PATH, false) == null)
{
String initValue = "AAA";
myWatch.createZNode(PATH, initValue);
logger.info("***************main: " + myWatch.getZNode(PATH));
Thread.sleep(Long.MAX_VALUE);
}else {
logger.info("***************have node*******");
}
}
// setter------getter
public ZooKeeper getZk()
{
return zk;
}
public void setZk(ZooKeeper zk)
{
this.zk = zk;
}
public String getOldValue()
{
return oldValue;
}
public void setOldValue(String oldValue)
{
this.oldValue = oldValue;
}
}
3 实现负载均衡的服务
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import com.atguigu.zk.watch.WatchMore;
public class BalanceTest
{
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(WatchMore.class);
// 定义常量
private static final String CONNECTSTRING = "192.168.31.167:2181";
private static final int SESSION_TIMEOUT = 50 * 1000;
private static final String PATH = "/atcunzi";
private static final String SUB_PREFIX = "sub";
// 定义实例变量
private ZooKeeper zk = null;
private List<String> serviceLists = new ArrayList<String>(); // sub1,.....sub5 // 用来收集可用服务的
private int subCount = 5; // 可用服务个数
private int currentServiceNum = 0; // 当前请求序号
// 初始化zookeepr,并获取服务的集合
public ZooKeeper startZK() throws IOException
{
return new ZooKeeper(CONNECTSTRING, SESSION_TIMEOUT,new Watcher() {
@Override
public void process(WatchedEvent event)
{
try
{
serviceLists = zk.getChildren(PATH,true);
}catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
});
}
// 处理轮询算法逻辑 重要的是怎么能让服务 轮询
public String dealRquest() throws KeeperException, InterruptedException
{
currentServiceNum = currentServiceNum + 1;
for (int i = currentServiceNum; i <=subCount; i++)
{
if(serviceLists.contains(SUB_PREFIX+currentServiceNum))
{
return new String(zk.getData(PATH+"/"+SUB_PREFIX+currentServiceNum,false,new Stat()));
}else{
currentServiceNum = currentServiceNum + 1;
}
}
//重要的是怎么能让服务 轮询 1 3 5 currentServiceNum = 6
for (int i = 1; i <=subCount; i++)
{
if(serviceLists.contains(SUB_PREFIX+i))
{
currentServiceNum = i;
return new String(zk.getData(PATH+"/"+SUB_PREFIX+currentServiceNum,false,new Stat()));
}
}
return "no subNode~~~~~";
}
public static void main(String[] args) throws IOException, InterruptedException
{
BalanceTest test = new BalanceTest();
test.setZk(test.startZK());
Thread.sleep(3000);
String result = null;
for (int i = 1; i <=15; i++)
{
try
{
result = test.dealRquest();
logger.info("*********customerID: "+i+"\t currentWindows:"+test.currentServiceNum+"\t"+result);
Thread.sleep(2000);
}
catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
///----setter=-=getter
public ZooKeeper getZk()
{
return zk;
}
public void setZk(ZooKeeper zk)
{
this.zk = zk;
}
}
4 总结
负载均衡可以看成一个银行,请求看成是顾客,后台服务看成是银行柜台,大堂经理可以看成zookeeper
服务启动的时候,需要先准备各个银行柜台都准备好,当顾客来到时候,可以 通过大堂经理的指引,去到相应的柜台进行柜台处理。
难点:当一个柜台暂停服务时候,大唐经理怎么知道的,并且怎么分发处理,并且服务怎么轮询的?
5 maven配置
<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.atguigu.zk1014</groupId>
<artifactId>zk1014</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>zk1014</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.101tec/zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>