SpringCloud整合Zookeeper代替Eureka

一、什么是Zookeeper?

1、Zookeeper是一个基于观察者设计模式的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者注册;

一旦这些数据的状态发生变化,Zookeeper就将负责通知以及在Zookeeper上注册的那些观察者做出相应的反应;

从而实现集群中类似Master/Slave管理模式!

2、一句话,简而言之—— Zookeeper = 文件系统 + 通知机制

Zookeeper也是一个倒装式的文件系统;——类似于linux

3、Zookeeper能干些什么?

  • 命名服务:统一命名服务,如Dubbo的服务注册中心;

  • 配置服务:如淘宝开源配置管理框架Diamond,在大型的分布式系统中,为了服务海量的请求,同一个应用常常需要多个实例。如果存在配置更新的需求,常常需要逐台更新,给运维增加了很大的负担,同时带来了一定的风险(哦诶之会存在不一致的窗口期,或个别节点忘记更新)。Zookeeper可以用来做几种的配置管理,存储在zookeeper集群中的配置,如果发生变更会主动推送到连接配置中心的应用节点,实现一处更新处处更新的效果!

32.jpg

  • 集群管理:如Hadoop分布式集群管理;

  • 分布式消息同步和协调机制:

  • 负载均衡:

  • 对Dubbo的支持:

  • Zookeeper提供了一套很好的分布式集群管理机制,就是它这种基于层次型的目录树的数据结构,并对树中的节点进行有效管理,

    从而可以设计出多种多样的分布式的数据管理模型,作为分布式系统的沟通调度桥梁


二、Zookeeper的安装配置

官网下载安装包,本次版本选择zookeeper-3.4.9.tar.gz

1、在根目录创建一个专门给zookeeper工作的目录;

33.jpg

2、拷贝下载好的zookeeper安装包到 /opt 目录下并解压,之后再将解压包拷贝到 /myzookeeper 目录下:

34.jpg

3、进入 /myzookeeper/zookeeper-3.4.9/conf 文件夹下,拷 zoo_sample.cfg 为 zoo.cfg:

35.jpg

4、修改zookeeper的核心配置文件 zoo.cfg,解读其关键配置:

  • tickTime: 通信的心跳间隔时间,单位为毫秒,默认为 2000ms;

  • initLimit: 集群中Follower 与Leader 之间初始连接时能容忍的最多心跳数;

  • syncLimit: 集群中Leader与Follower之间的最大响应时间,如果超过,Leader就认为Follower死掉了,姜葱服务列表中移除Follower;

  • dataDir: 数据目录;

  • clientPort: 默认端口 :2181

5、直接开启服务(解压直接用):——机器必须已经安装了JDK,因为Zookeeper服务器使用java编写的,需要jvm;

  • 启动服务:./zkServer.sh start

    可以使用另一个客户端,和zookeeper互动:

    37.jpg

  • 关闭服务:./zkServer.sh stop

  • 客户端连接:./zkCli.sh

    36.jpg

  • 退出:quit

  • 创建节点:create /testNode v1

  • 获取节点的值:get /testNode

    39.jpg

  • 重新设置节点的值:set /testNode v2

  • 删除节点:delete /testNode

    操作 zookeeper 就仿佛在操作一个Map一样简单,只不过它的 key 是一个路径path而已!


三、使用Zookeeper代替Eureka,作为服务注册中心

40.jpg

1、关闭防火墙(我是用的是Ubuntu系统):sudo ufw disable

41.jpg 

如果是Centos系统,则使用命令:sudo systemctl stop firewalld

确保zookeeper所在机器与本机测试环境相互 ping 通:

42.jpg

2、快速创建一个新的支付服务提供者 cloud-provider-payment8004

pom.xml文件:只需要将Eureka客户端的依赖,换成zookeeper客户端的依赖即可(简单的做个服务,数据库4项就不要了):

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.jiguiquan.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8004</artifactId>

    <dependencies>
        <!--公共服务模块依赖-->
        <dependency>
            <groupId>com.jiguiquan.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--springboot项目web和actuator最好一起走-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--SpringBoot整合zookeeper的客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>

        <!--热部署devtools-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
</project>

3、配置文件application.yml如下:

server:
  port: 8004

spring:
  application:
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: 192.168.44.129:2181

4、主启动类 com.jiguiquan.springcloud.PaymentMain8004.java:

@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为服务中心时,向其注册服务,以后很常见
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class, args);
    }
}

5、写个最简单的 PaymentController:

@RestController
@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;

    @RequestMapping("/payment/zk")
    public String paymentzk(){
        return "Springcloud with zookeeper: "+ serverPort + "\t" + UUID.randomUUID().toString();
    }
}

6、先启动Zookeeper服务,使用zkCli连接:

...启动服务端
root@Ubuntu:/myzookeeper/zookeeper-3.4.9/bin# ./zkServer.sh start
...使用zkCli客户端连接
root@Ubuntu:/myzookeeper/zookeeper-3.4.9/bin# ./zkCli.sh
...zookeeper下除了原始的 /zookeeper节点外,没有任何其他节点!!
[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 1] get /zookeeper

cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: localhost:2181(CONNECTED) 2]

7、此时启动 cloud-provider-payment8004 项目,直接报错

44.jpg

究其原因,真如截图所说,是因为我们映入的jar包中自带的zookeeper的版本为zookeeper-3.5.3-beta.jar:

45.jpg

处理办法:

  • 卸载服务器上的zookeeper服务,换为3.5.3?显然不可以,因为此zookeeper可能有很多服务都在用,不能轻易卸载!!

  • 从本Java程序入手,将spring-cloud-start-zookeeper-discovery依赖自带的zookeeper排除掉,换成我们需要的zookeeper版本即可——可行!

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    <!--排除此starter依赖自带的zookeeper版本,换成我们自己需要的zookeeper版本-->
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.9</version>
</dependency>

8、再次启动 cloud-provider-payment8004 服务,此次,没有报任何的错误:

具体,有没有注册成功,我们可以使用 .zkCli.sh 客户端连接到 zookeeper 查看:

[zk: localhost:2181(CONNECTED) 2] ls /
[services, zookeeper]
[zk: localhost:2181(CONNECTED) 3] ls /services
[cloud-provider-payment]

很明显,cloud-provider-payment 服务已经成功入驻进 zookeeper 服务;

9、我们继续向下深挖:

46.jpg

将其中的服务详细信息格式化后看一下:

{
    "name":"cloud-provider-payment",
    "id":"50ff9ca1-3868-4358-bcfa-f6a68b57be76",
    "address":"localhost",
    "port":8004,
    "sslPort":null,
    "payload":{
        "@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
        "id":"application-1",
        "name":"cloud-provider-payment",
        "metadata":{

        }
    },
    "registrationTimeUTC":1584029149663,
    "serviceType":"DYNAMIC",
    "uriSpec":{
        "parts":[
            {
                "value":"scheme",
                "variable":true
            },
            {
                "value":"://",
                "variable":false
            },
            {
                "value":"address",
                "variable":true
            },
            {
                "value":":",
                "variable":false
            },
            {
                "value":"port",
                "variable":true
            }
        ]
    }
}

可以,很清楚看出来,此服务 cloud-provider-payment8004 注册在 Zookeeper 中的详细信息!

10、服务注册进Zookeeper后,是临时节点还是持久节点?

zookeeper有四种节点:

  • 临时节点;

  • 临时有序节点;

  • 持久节点;

  • 持久有序节点;

经过简单对payment8004的启停,可以发现在简单心跳检测时间后,zookeeper就会将对应的节点删除,

可以知道zookeeper作为服务注册中心,创建的是临时节点;

且Zookeeper没有类似于Eureka那样的自我保护机制;


四、创建订单服务cloud-consumerzk-order80服务,并注册进Zookeeper

1、创建module,pom.xml如下:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.jiguiquan.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumerzk-order80</artifactId>

    <dependencies>
        <!--公共服务模块依赖-->
        <dependency>
            <groupId>com.jiguiquan.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--springboot项目web和actuator最好一起走-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--SpringBoot整合zookeeper的客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--排除此starter依赖自带的zookeeper版本,换成我们自己需要的zookeeper版本-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </dependency>

        <!--热部署devtools-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
</project>

2、application.yml如下:

server:
  port: 80

spring:
  application:
    name: cloud-consumerzk-order
  cloud:
    zookeeper:
      connect-string: 192.168.44.129:2181

3、编写主启动类:OrderZKMain80.java:

@SpringBootApplication
@EnableDiscoveryClient
public class OrderZKMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderZKMain80.class, args);
    }
}

4、编写简单业务类OrderController.java:

@RestController
@Slf4j
public class OrderZkController {
    public static final String INVOKE_URL = "http://cloud-provider-payment";
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/zk")
    public String paymentInfo(){
        return restTemplate.getForObject(INVOKE_URL + "/payment/zk", String.class);
    }
}

5、启动服务cloud-consumerzk-order80,之后检查zookeeper中的节点列表:

47.jpg

可见,Order80已经注册进了Zookeeper;

6、使用以下路径访问:http://localhost/consumer/payment/zk

48.jpg

访问正常!Zookeeper作为服务注册中心,一切正常!Over

个人此项目代码地址(持续更新):

https://github.com/jiguiquan/cloud2020

jiguiquan@163.com

文章作者信息...

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐