文章目录
- 1.服务注册的简单介绍
- 2.使用zookeeper注册服务
- 3.服务发现
- 4.Eureka与Zookeeper作为注册中心的区别
参考蚂蚁课堂
1.服务注册的简单介绍
这个微服务之间的相互调用和上面的图类似,首先会有一个注册中心,生产者把自己的IP地址与端口号注册到注册中心上,然后消费者从注册中心获取生产者的IP地址和端口号,然后通过本地RPC远程调用生产者服务。
如果我们用zookeeper实现服务注册的话那就是在zookeeper下面创建节点比如说/payment-service(服务名称),如果是一个集群的话下面就可以创建/payment-service/s0,/payment-service/s1…。
2.使用zookeeper注册服务
首先再启动之后我们首先将服务注册进zookeeper中,
@Component
public class ApplicationRunnerImpl implements ApplicationRunner {
// SpringBoot启动成功之后 回调执行的方法
//参数1 连接地址
private static final String ADDRES = "192.168.247.3:2181";
// 参数2 zk超时时间
private static final int TIMEOUT = 5000;
// 计数器
private static CountDownLatch countDownLatch = new CountDownLatch(1);
@Value("${server.port}")
private String serverPort;
@Override
public void run(ApplicationArguments args) throws Exception {
ZooKeeper zooKeeper = new ZooKeeper(ADDRES, TIMEOUT, new Watcher() {
// 获取该连接是否成功
@Override
public void process(WatchedEvent watchedEvent) {
Event.KeeperState state = watchedEvent.getState();
if (state == Event.KeeperState.SyncConnected) {
System.out.println("zk连接成功");
// 计数器减去1
countDownLatch.countDown();
}
}
});
countDownLatch.await();
// 1. 判断父节点是否存在
String parentPath = "/payment-service";
Stat exists = zooKeeper.exists(parentPath, null);
// 2. 创建我们的子节点
if (exists == null) {
// 父亲节点不存在
zooKeeper.create(parentPath, "payment".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
// 3.实现我们的服务注册
String path = "http://127.0.0.1:" + serverPort;
zooKeeper.create(parentPath + "/" + serverPort, path.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
System.out.println("服务注册成功" + parentPath);
}
}
首先我们创建zookeeper连接,放一个countDownLatch防止zookeeper连接失败导致的问题。然后连接创建成功之后,我们看看父节点也就是服务名称存不存在,如果不存在则创建父节点权限是开放的,父节点也应该是持久化的,然后创建子节点把子节点的IP地址和端口号写上实现服务注册。这个port通过yml文件读取。yml文件标好端口号。
再来一个启动类
@SpringBootApplication
public class AppSpring {
public static void main(String[] args) {
SpringApplication.run(AppSpring.class);
}
}
3.服务发现
我们可以通过连接zk,获取里面节点的内容,即我可以发现上述两个服务的IP + 端口号。
public class Test1 {
private static final CountDownLatch countDownLatch = new CountDownLatch(1);
//参数1 连接地址
private static final String ADDRES = "192.168.247.3:2181";
// 参数2 zk超时时间
private static final int TIMEOUT = 5000;
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper(ADDRES, TIMEOUT, new Watcher() {
// 获取该连接是否成功
@Override
public void process(WatchedEvent watchedEvent) {
Event.KeeperState state = watchedEvent.getState();
if (state == Event.KeeperState.SyncConnected) {
System.out.println("zk连接成功");
// 计数器减去1
countDownLatch.countDown();
}
}
});
countDownLatch.await();
// 1. 判断父节点是否存在
String parentPath = "/payment-service";
List<String> children = zooKeeper.getChildren(parentPath,null,new Stat());
for(int i = 0;i < children.size();i++){
String pathChildren = parentPath + "/" + children.get(i);
byte[] data = zooKeeper.getData(pathChildren, null, new Stat());
System.out.println("服务接口地址" + new String(data));
}
}
}
由此我们能清晰的看到服务被成功发现。
4.Eureka与Zookeeper作为注册中心的区别
- 相同点:Eureka和Zookeeper都可以作为服务注册中心。
- 不同点:Zookeeper保证CP数据一致性(原理采用ZAB原子广播协议),当zk宕机之后,会重新选举leader(恢复机制),如果恢复时间过长,或者投票没超过半数,那么整个zk集群不可用,意味着服务注册中心不可用。
Eureka保证AP,设计思想优先考虑可用性,完全去中心化服务注册中心,每个节点都是均等的,没有主从之分,几个节点挂了不会影响Eureka的使用,Eureka客户端发现连接时不可用的话,自动切换到下个Eureka连接。
SpringCloud使用Eureka而不是Zookeeper,因为服务中心注册,可以短暂接收数据不一致,但不能接受不可用。