• Spring Cloud Zookeeper搭建实例


    1. 简介

    本文将介绍如何使用Zookeeper在微服务框架中实现服务发现,该服务发现机制可作为云服务的注册中心。通过Spring Cloud Zookeeper为应用程序提供一种Spring Boot集成,将Zookeeper通过自动配置和绑定 的方式集成到Spring环境中。

    在本例子中我们将创建两个应用程序:

    • 提供服务的应用程序(称为 服务提供者
    • 使用此服务的应用程序(称为 服务消费者

    2. 安装Zookeeper

    2.1 下载

    Apache官方最新版本为:3.4.8
    下载地址:http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz

    2.2 安装

    解压到指定目录下 D:softzookeeper-3.4.8 修改zoo_sample.cfg 文件名(D:softzookeeper-3.4.8conf) 为 zoo.cfg主要修改一下日志位置,具体配置文件如下:

    # The number of milliseconds of each tick
    tickTime=2000
    # The number of ticks that the initial 
    # synchronization phase can take
    initLimit=10
    # The number of ticks that can pass between 
    # sending a request and getting an acknowledgement
    syncLimit=5
    # the directory where the snapshot is stored.
    # do not use /tmp for storage, /tmp here is just 
    # example sakes.
    dataDir=D:\zookeeper\data
    dataLogDir=D:\zookeeper\log
    # the port at which the clients will connect
    clientPort=2181
    # the maximum number of client connections.
    # increase this if you need to handle more clients
    #maxClientCnxns=60
    #
    # Be sure to read the maintenance section of the 
    # administrator guide before turning on autopurge.
    #
    # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
    #
    # The number of snapshots to retain in dataDir
    #autopurge.snapRetainCount=3
    # Purge task interval in hours
    # Set to "0" to disable auto purge feature
    #autopurge.purgeInterval=1
    
    • tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
    • dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
    • dataLogDir:顾名思义就是 Zookeeper 保存日志文件的目录
    • clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

    2.3 启动

    进入到bin目录,并且启动zkServer.cmd,这个脚本中会启动一个java进程,双击该文件即可启动:

    file

    3. 搭建服务提供者

    我们将创建一个服务提供者,通过增加pring-cloud-starter-zookeeper-discovery依赖和在主程序中引入@EnableDiscoveryClient注释。服务的具体内容是通过GET请求返回“Hello World!”字符串。
    整个项目结构如下:

    file

    3.1 导入依赖

    <?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">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.yiidian</groupId>
        <artifactId>spring-cloud-zookeeper-proivder</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.1.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <!-- SpringBoot 对Web支持  SpringMVC相关功能,json转换的功能等等 -->
            <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>
        </dependencies>
    
        <!-- 定义SpringCloud版本 -->
        <repositories>
            <repository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
            <repository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Finchley.M9</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </project>
    

    3.2 启动类

    使用@EnableDiscoveryClient注释我们的主类,这将使HelloWorld 应用程序自动发布。

    package com.yiidian.provider;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    /**
     * 服务提供者启动类
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    public class ProviderStarter {
    
        public static void main(String[] args) {
            SpringApplication.run(ProviderStarter.class,args);
        }
    
    }
    
    

    3.3 Controller

    package com.yiidian.provider.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 一点教程网: http://www.yiidian.com
     * 控制器
     */
    @RestController
    public class HelloController {
    
        @GetMapping("/hello")
        public String hello(){
            return "Hello World";
        }
    
    }
    
    

    3.4 配置application.yml

    在application.yml中定义服务名称用来被客户端调用,同时配置Zookeeper信息用来注册服务。

    server:
      port: 9001
    spring:
      application:
        name: Provider
      cloud:
        zookeeper:
          discovery:
            enabled: true
          connect-string: localhost:2181
    logging:
      level:
        org.apache.zookeeper.ClientCnxn: WARN
    

    4. 搭建服务消费者

    现在我们来创建一个REST服务消费者,它使用spring Netflix Feign Client来调用服务。先看看整个项目结构:
    file

    4.1 导入依赖

    在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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.yiidian</groupId>
        <artifactId>spring-cloud-zookeeper-consumer</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.1.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <!-- SpringBoot 对Web支持  SpringMVC相关功能,json转换的功能等等 -->
            <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.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 定义SpringCloud版本 -->
        <repositories>
            <repository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
            <repository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Finchley.M9</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </project>
    

    4.2 启动类

    同服务提供者一样在主程序中增加@EnableDiscoveryClient 注解。

    package com.yiidian.consumer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    /**
     *服务消费者启动类
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class ConsumerStarter {
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerStarter.class,args);
        }
    
    }
    
    

    4.3 定义Feign远程接口

    通过引入spring-cloud-starter-openfeign组件包使用声明式服务调用方式调用远程服务,使用@FeignClient(“service-name”)注解一个接口并将它自动连接到我们的应用程序中,以便我们以编程方式访问此服务。

    package com.yiidian.consumer.client;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    
    /**
     * Feign远程接口
     */
    @FeignClient("Provider")
    public interface HelloClient {
    
        @GetMapping("/hello")
        public String hello();
    }
    
    

    4.4 Controller

    以下是一个简单的服务控制器类,它通过注入接口helloWorldClient对象调用服务提供者的接口来消费该服务,并在响应中显示它的返回值。

    package com.yiidian.consumer.controller;
    
    import com.yiidian.consumer.client.HelloClient;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 消费者控制器
     */
    @RestController
    public class GreetingController {
    
        @Autowired
        private HelloClient helloClient;
    
        @GetMapping("/get-greeting")
        public String greeting() {
            return helloClient.hello();
        }
    
    }
    
    

    4.5 配置application.yml

    server:
      port: 9002
    spring:
      application:
        name: Consumer
      cloud:
        zookeeper:
          discovery:
            enabled: true
          connect-string: localhost:2181
    logging:
      level:
        org.apache.zookeeper.ClientCnxn: WARN
    
    

    5. 测试

    HelloWorld REST服务在Zookeeper中注册了自己,Greeting服务通过声明式客户端发现和调用HelloWorld 服务。

    现在我们可以运行这两个服务,然后在浏览器中访问 http://localhost:9002/get-greeting,将返回以下信息:

    file

    6. 总结

    在本文中我们看到了如何使用Spring Cloud Zookeeper实现服务发现,并且在Zookeeper中注册了一个名为Hello World的服务。然后通过声明式服务调用方式实现了一个服务消费者Greeting来发现和使用该服务。

    顺便介绍下ZookeeperEureka这两种服务治理框架的区别。Spring Cloud Eureka实现的服务治理机制强调了CAP原理中的AP,即可用性可靠性,而Zookeeper强调CP(一致性可靠性)。Eureka为了实现更高的服务可用性,牺牲了一定的一致性,在极端情况下它宁愿接受故障实例也不要丢掉“健康”实例,比如,当服务注册中心的网络发生故障断开时,由于所有的服务实例无法维持续约心跳,在强调CP的服务治理中将会把所有服务实例都剔除掉,而Eureka则会触发保护机制,保留此时的所有节点,以实现服务间依然可以进行互相调用的场景。

    file

    欢迎关注我的公众号::一点教程。获得独家整理的学习资源和日常干货推送。
    如果您对我的系列教程感兴趣,也可以关注我的网站:yiidian.com

  • 相关阅读:
    使用yarn来替代npm
    React及Nextjs相关知识点小结
    appstore-react v2.0—redux-actions和redux-saga的应用
    开机SystemServer到ActivityManagerService启动过程分析
    java 读取气象专业格式NetCDF文件
    maven项目对于maven远程仓库没有资源的解决办法
    leaflet 使用kriging.js实现前端自定义插值
    leaflet 使用高德地图实例
    uni-app上使用leaflet地图的解决方案
    MySQL创建新用户并且赋予权限
  • 原文地址:https://www.cnblogs.com/yiidian/p/12411593.html
Copyright © 2020-2023  润新知