spring cloud 整合 zookeeper及zookeeper集群使用
ZooKeeper1 zookeeper简介ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用
ZooKeeper
1 zookeeper简介
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_home\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
ZooKeeper是以Fast Paxos算法为基础的,[Paxos 算法](https://baike.baidu.com/item/Paxos 算法)存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos做了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解。
ZooKeeper的基本运转流程:
1、选举Leader。
2、同步数据。
3、选举Leader过程中算法有很多,但要达到的选举标准是一致的。
4、Leader要具有最高的执行ID,类似root权限。
5、集群中大多数的机器得到响应并接受选出的Leader。
选举流程
1、 当leader挂了后,其他非observer的机器变更状态为looking,然后开始选举流程
2、每个server都会发出一个投票信息(myid,zxid)
3、接收来自各个服务器的投票
4、处理投票–判断zxid,大的zxid成为leader,如果zxid相同,就判断myid,myid大的做leader
5、统计投票–半数服务器达成一致意见后,投票结束
6、改变自身的状态–leader为leading,其他服务器为following
2 zookeeper安装与启动
https://www.yiibai.com/zookeeper/zookeeper_installation.html
https://blog.csdn.net/zlbdmm/article/details/109669049
zoo.cfg 配置文件说明:
- tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
- initLimit:LF初始通信时限,集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量)。
- syncLimit:LF同步通信时限,集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)。
- dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
- clientPort:客户端连接端口,这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求
- autopurge.snapRetainCount:保留数量。
- autopurge.purgeInterval:清理时间间隔,单位:小时。
- server.N = YYY:A:B,其中N表示服务器编号,YYY表示服务器的IP地址,A为LF通信端口,表示该服务器与集群中的leader交换的信息的端口。B为选举端口,表示选举新leader时服务器间相互通信的端口(当leader挂掉时,其余服务器会相互通信,选择出新的leader)。一般来说,集群中每个服务器的A端口都是一样,每个服务器的B端口也是一样。但是当所采用的为伪集群时,IP地址都一样,只能时A端口和B端口不一样。
3 集成springcloud 服务注册
IDEA使用spring initializr创建服务,勾选下图依赖
成功后,完整pom如下
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cuixk.microserver.zookeeper</groupId>
<artifactId>zookeeper-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>zookeeper-provider</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.0</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
服务生产者配置文件
server:
port: 8000
spring:
cloud:
zookeeper:
connect-string: 192.168.20.134:2181
discovery:
enabled: true
application:
name: zookeeper-provider
服务消费者配置文件
server:
port: 8001
spring:
cloud:
zookeeper:
connect-string: ip:2181 #zookeeper服务地址
discovery:
enabled: true #开启服务发现功能
application:
name: zookeeper-consumer #应用ID
服务生产者在启动类上添加@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class ZookeeperProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ZookeeperProviderApplication.class, args);
}
}
服务消费者在启动类上添加@EnableDiscoveryClient,@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ZookeeperConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ZookeeperConsumerApplication.class, args);
}
}
启动项目,如下图所示即注册成功
4 测试
通用pojo
@Data
public class User {
private Integer id;
private String name;
private Integer age;
}
服务生产者
controller代码
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public User getUserInfo(@PathVariable Integer id) {
User user = new User();
user.setId(id);
user.setName("provider");
user.setAge(25);
return user;
}
}
服务消费者
controller代码
@RestController
@RequestMapping("/get")
public class OrderController {
@Resource
private UserFeign userFeign;
@GetMapping("/{id}")
public String getUserInfo(@PathVariable Integer id) {
User userInfo = userFeign.getUserInfo(id);
return userInfo.toString();
}
}
feign代码
@FeignClient("zookeeper-provider") //此处填写服务生产者注册的serviceName
public interface UserFeign {
@GetMapping("/user/{id}")
User getUserInfo(@PathVariable Integer id);
}
调用消费者接口,若有结果返回,则测试通过。
5 问题记录
5.1zookeeper 启动异常 myid文件缺失导致zookeeper无法启动(myid file is missing)
https://blog.csdn.net/u010842515/article/details/51147016
5.2 按照springcloud官网测试代码,发现无法获取到client信息,始终返回null值。
@Autowired
private DiscoveryClient discoveryClient;
public String serviceUrl() {
List<ServiceInstance> list = discoveryClient.getInstances("STORES");
if (list != null && list.size() > 0 ) {
return list.get(0).getUri().toString();
}
return null;
}
原因:
1.discoveryClient.getInstances(“STORES”); 此处入参需改成实际注册的serviceName
2.需开启服务发现注解 @EnableDiscoveryClient
6 zookeeper集群搭建
https://blog.csdn.net/zlbdmm/article/details/109669049
由上述链接集群搭建成功后,修改配置文件
connect-string 配置了所有zk节点,原因并不是为了向所有zk注册信息,而是如果 zk1挂掉之后,转向其他zk注册,保证服务可以注册成功
消费者配置文件
server:
port: 8001
spring:
cloud:
zookeeper:
connect-string: localhost:12181,localhost:12182,localhost:12183
discovery:
enabled: true
application:
name: zookeeper-consumer
生产者配置文件
server:
port: 8081
spring:
application:
name: service-provider
cloud:
nacos:
discovery:
server-addr: 192.168.20.134:8848
进行第 4 节的测试工作。
Zookeeper集群数为单数
1、容错
由于在增删改操作中需要半数以上服务器通过,来分析以下情况。
2台服务器,至少2台正常运行才行(2的半数为1,半数以上最少为2),正常运行1台服务器都不允许挂掉
3台服务器,至少2台正常运行才行(3的半数为1.5,半数以上最少为2),正常运行可以允许1台服务器挂掉
4台服务器,至少3台正常运行才行(4的半数为2,半数以上最少为3),正常运行可以允许1台服务器挂掉
5台服务器,至少3台正常运行才行(5的半数为2.5,半数以上最少为3),正常运行可以允许2台服务器挂掉
6台服务器,至少3台正常运行才行(6的半数为3,半数以上最少为4),正常运行可以允许2台服务器挂掉
通过以上可以发现,3台服务器和4台服务器都最多允许1台服务器挂掉,5台服务器和6台服务器都最多允许2台服务器挂掉
但是明显4台服务器成本高于3台服务器成本,6台服务器成本高于5服务器成本。这是由于半数以上投票通过决定的。
2、防脑裂
一个zookeeper集群中,可以有多个follower、observer服务器,但是必需只能有一个leader服务器。
如果leader服务器挂掉了,剩下的服务器集群会通过半数以上投票选出一个新的leader服务器。
集群互不通讯情况:
一个集群3台服务器,全部运行正常,但是其中1台裂开了,和另外2台无法通讯。3台机器里面2台正常运行过半票可以选出一个leader。
一个集群4台服务器,全部运行正常,但是其中2台裂开了,和另外2台无法通讯。4台机器里面2台正常工作没有过半票以上达到3,无法选出leader正常运行。
一个集群5台服务器,全部运行正常,但是其中2台裂开了,和另外3台无法通讯。5台机器里面3台正常运行过半票可以选出一个leader。
一个集群6台服务器,全部运行正常,但是其中3台裂开了,和另外3台无法通讯。6台机器里面3台正常工作没有过半票以上达到4,无法选出leader正常运行。
通可以上分析可以看出,为什么zookeeper集群数量总是单出现,主要原因还是在于第2点,防脑裂,对于第1点,无非是正本控制,但是不影响集群正常运行。但是出现第2种脑裂的情况,zookeeper集群就无法正常运行了。
7 参考链接
https://docs.spring.io/spring-cloud-zookeeper/docs/current/reference/html/ 官方网址
https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.5.9/apache-zookeeper-3.5.9-bin.tar.gz 下载地址
https://www.yiibai.com/zookeeper/zookeeper_installation.html zookeeper安装与启动
https://cloud.tencent.com/developer/article/1505113 服务注册发现之Zookeeper服务注册
https://blog.csdn.net/zlbdmm/article/details/109669049 Zookeeper下载与安装教程(for windows)
https://blog.csdn.net/CSDN_Stephen/article/details/78856323 用Zookeeper作为Spring cloud的配置中心
更多推荐
所有评论(0)