CAP:
C:一致性>Consistency;
取舍:(强一致性、单调一致性、会话一致性、最终一致性、弱一致性)
A:可用性>Availability;
P:分区容错性>Partition tolerance;
1、ZK(文件系统+监听机制watcher<观察者模式>):
配置JAVA环境:java -version;
下载解压zookeeper:
wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.12.tar.gz;
tar -zxvf zookeeper-3.4.12.tar.gz; *.sh start;
重命名配置文件:cp conf/zoo_sample.cfg conf/zoo.cfg;
vim conf/zoo.cfg
dataDir=/usr/local/data/zookeeper-1
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
zoo.cfg复制两个配置文件(其只需修改dataDir和clientPort即可.)
启动zk
创建集群根节点:/GroupMembers
服务提供与消费
public class ZkServiceConsumer implements Watcher {
private static final Logger logger = LoggerFactory.getLogger(ZkServiceConsumer.class);
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zk = null;
private static String root = "/GroupMembers";
public static void main(String[] args) throws Exception {
zk = new ZooKeeper("xxx.xxx.x.xx:2181", 5000, new ZkServiceConsumer());
countDownLatch.await();
List childrenList = zk.getChildren(root, true);
logger.info("服务Provider:{}", childrenList);
childrenList.forEach(child -> {
try {
logger.info(child + ":" + new String(zk.getData(root + "/" + child, false, new Stat())));
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread.sleep(Integer.MAX_VALUE);
}
@Override
public void process(WatchedEvent event) {
if (Event.KeeperState.SyncConnected == event.getState()) {
if (event.getType() == Event.EventType.None && event.getPath() == null) {
countDownLatch.countDown();
} else if (event.getType() == Event.EventType.NodeChildrenChanged) {
try {
List childrenList = zk.getChildren(event.getPath(), true);
logger.info("更新服务提供者列表:{}", childrenList);
for (String child : childrenList) {
logger.info(child + new String(zk.getData(root + "/" + child, false, new Stat())));
}
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
创建集群节点n1
创建集群节点n2
同n1(port:8082)
public class ZkProSync implements Watcher {
private static final Logger logger = LoggerFactory.getLogger(ZkProSync.class);
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zk = null;
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception {
String path = "/username";
zk = new ZooKeeper("xxx.xxx.x.xx:2181", 5000, new ZkProSync());
countDownLatch.await();
logger.info(new String(zk.getData(path, true, stat)));
Thread.sleep(Integer.MAX_VALUE);
}
@Override
public void process(WatchedEvent event) {
if (Event.KeeperState.SyncConnected == event.getState()) {
if (event.getType() == Event.EventType.None && event.getPath() == null) {
countDownLatch.countDown();
} else if (event.getType() == Event.EventType.NodeDataChanged) {
try {
logger.info("配置已更改为:{}", new String(zk.getData(event.getPath(), true, stat)));
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
<其中Consistency:zk保证了最终一致性,Sync到各个节点.>
2、Eureka
eureka不会有类似于zk选举leader的过程,若某台服务器宕机,客户端请求自动切换到新的eureka节点,当宕机的服务器恢复后,eureka则再次将其纳入到服务器集群管理之中,即同步新的服务注册信息。
1.CP VS 2.AP
ZK定位于分布式协调服务,在其管辖下的所有服务之间保持同步、一致(Zab算法,CP),若作Service发现服务,其本身没有正确处理网络分割的问题<当多个zk之间网络出现问题-造成出现多个leader-脑裂>,即在同一个网络分区的节点数达不到zk选取leader的数目,它们就会从zk中断开,同时也不能提供Service发现服务l。
Eureka相对于ZK剔除了选取Leader或事务日志机制,它有独立的客户端程序库,同时提供心跳、服务健康监测、自动发布等服务与自动刷新缓存的功能,在网络分割故障发生时,每个节点会持续的对外提供服务,接收新的服务注册同时将它们提供给下游的服务发现请求(AP)l。