3--SpringCloud 和 Zookeeper周阳老师

2021:3--SpringCloud 和 Zookeeper

https://www.cnblogs.com/coderD/p/14350076.html SpringCloud

https://www.cnblogs.com/coderD/p/14350073.html SpringCloud 和 Eureka

https://www.cnblogs.com/coderD/p/14350082.html SpringCloud 和 Zookeeper

https://www.cnblogs.com/coderD/p/14350086.html SpringCloud-Ribbon/OpenFeign

https://www.cnblogs.com/coderD/p/14350091.html SpringCloud:Hystrix 断路器

https://www.cnblogs.com/coderD/p/14350097.html SpringCloud:服务网关 gateway

https://www.cnblogs.com/coderD/p/14350099.html SpringCloud:Config/Bus

https://www.cnblogs.com/coderD/p/14350103.html SpringCloud:Stream/Sleuth

https://www.cnblogs.com/coderD/p/14350110.html SpringCloud Alibaba:Nacos

https://www.cnblogs.com/coderD/p/14350114.html SpringCloud Alibaba:Sentinel

https://www.cnblogs.com/coderD/p/14350119.html SpringCloud Alibaba:Seata

代码:https://gitee.com/xue--dong/spring-cloud

阳哥脑图:https://gitee.com/xue--dong/spring-cloud

主要内容

1.  服务注册中:Zookeeper代替Eureka

2.   Consul服务注册与发现
复制代码

1. 注册中心 Zookeeper

zookeeper是一个分布式协调工具,可以实现注册中心功能

关闭linux服务器防火墙后,启动zookeeper服务器
systemctl stop firewalld

zookeeper服务器取代Eureka服务器,zk作为服务注册中心
复制代码

2. 服务提供者

2.1 新建 cloud-provider-payment8004

1.  新建cloud-provider-payment8004
复制代码

2.2 pom

2.  pom
复制代码
<dependencies>

        <!--SpringBoot整合zookeeper客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>
        <!--引入我们自定义的公共api jar包-->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--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>

        <!--Mybatis和SpringBoot的整合-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <!--如果没写版本,从父层面找,找到了就直接用,全局统一-->
        </dependency>

        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>
复制代码

2.3 yml

3.  yml
复制代码
     server:
      port: 8004
    
    spring:
      application:
        name: cloud-provider-payment
      cloud:
        zookeeper:
          connect-string: 192.168.92.130:2181
    
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource      # 数据源
        driver-class-name: com.mysql.cj.jdbc.Driver     # mysql驱动包
        url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: root
复制代码

2.4 主启动类

4.  主启动类
复制代码
    @SpringBootApplication
    @EnableDiscoveryClient //开启服务发现
    public class PaymentMain8004 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8004.class, args);
        }
    }
复制代码

2.5 controller

5.  controller
复制代码
    @RestController
    public class PaymentController {
    
        @Value("${server.port}")
        private String serverPort;
    
        @RequestMapping(value="/payment/zk")
        public String paymentzk(){
            return "springcloud with zookeeper: "+serverPort+"\t"+ UUID.randomUUID().toString();
        }
    }

复制代码

2.6 测试:解决 jar 包冲突

6.  启动测试

    这里视频会出现一个jar冲突的异常
复制代码

img

    分析思路:
        
        找到代码中出错的地方,向启动入口处的报错,肯定是环境引起的。
        
        注意到提示zookeeper-3.5.6-beta。
        
        再想到我们自己安装的zookeeper版本,那就可能是jar包的冲突了。
        
        很可能是某个整合包自带的zookeeper包和我们服务器上的zookeeper版本不一样。
        
        发现我们导入的spring-zookeeper的整合包,包含了zookeeper-3.5.6-beta,我们要将其排除掉
复制代码

img

    怎么做:
    
        一般不会卸载zookeeper,因为其他系统可能正在使用这个zookeeper。
        
        所以我们排除掉包含的这个冲突的zookeeper包,引入一个服务器对应的jar包
        
7.  我这里没报错。

    不知道是不是我的版本(3.6.1)比较高的原因
    
    我试着将整合包中的3.5.3版本的zookeeper剔除掉,引入3.6.1
复制代码
        <!--SpringBoot整合zookeeper客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--排除掉自带的zookeepr3.5.3-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--引入对应服务器版本的zookeeper-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.6.1</version>
        </dependency>
复制代码
8.  启动:报错
    
    添加了3.6.1的zookeeper后,会报错:
复制代码

img

    那么很显然了,根据上面的分析,出错误在主启动类,关键词slf4j,logback。
    
    查看引入的3.6.1的zookeeper包:
复制代码

img

    我导入的slf4j:
复制代码

img

    我选择排除掉其中的3.6.1的zookeeper包其中的三个日志相关的jar包,用自己的。
复制代码

img

    成功排除掉。
    
    注意:groupId和artifactId的对应。
 
    重启服务:启动成功!!!

9.  查看一下服务是否注册成功

    1.  进入zookeeper容器中
    
        docker exec -it 66805aa71339 /bin/bash
        
    2.  客户端连接
    
        ./bin/zkCli.sh
复制代码

img

    3.  查看服务
    
        ls /
        ls /services
复制代码

img

        注册成功!!!
        
        继续进去看:
        
        ls /services/cloud-provider-payment
        
        ls /services/cloud-provider-payment/e3d40a33-8de3-4bc6-b560-d1b510211045
复制代码

img

    4.  几个概念
    
        1.  /services/cloud-provider-payment/e3d40a33-8de3-4bc6-b560-d1b510211045
        
        这整个东西就是zookeeper的zNode节点。
        
        
        2.  我们通过get命令,获取zookeeper中的节点信息
复制代码

img

            这一大串,就是我们服务存在zookeeper的基本信息--JSON串。
            
        3.  我们在线解析一下这个json串
复制代码

img

2.7 思考

10. 思考

        注册到zookeeper的微服务是一个zNode节点,这个服务节点时临时节点还是持久节点?
        
        我们注册进zookeeper的服务,会自动生成一个流水号id
复制代码

img

        1.  关闭掉8004服务
        
        2.  查看zookeeper中是否还有该微服务。
复制代码

img

            发现刚断开连接时zookeeper还保存着该服务,等待一段时间剔除了断开连接的微服务。
            
        3.  所以注册到zookeeper的微服务节点是临时节点。
        
        
        4.  再重新启动8004的微服务
复制代码

img

            服务又注册了进来,但是流水id换了。
            
        5.  zookeeper比eureka更加心狠干脆。
复制代码

3. 服务消费者

3.1 新建 cloud-consumerzk-order80

    1.  新建cloud-consumerzk-order80
复制代码

3.2 pom

        <dependencies>
    
            <!--SpringBoot整合zookeeper客户端-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
                <!--排除掉自带的zookeepr3.5.3-->
                <exclusions>
                    <exclusion>
                        <groupId>org.apache.zookeeper</groupId>
                        <artifactId>zookeeper</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--引入对应服务器版本的zookeeper-->
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.6.1</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-log4j12</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
    
            <!--引入我们自定义的公共api jar包-->
            <dependency>
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
    
            <!--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>
    
            <!--Mybatis和SpringBoot的整合-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <!--如果没写版本,从父层面找,找到了就直接用,全局统一-->
            </dependency>
    
            <!--mysql-connector-java-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!--jdbc-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <!--热部署-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </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>
复制代码

3.3 yml

    server:
      port: 80
    
    spring:
      application:
        name: cloud-consumerzk-order
      cloud:
        zookeeper:
          connect-string: 192.168.92.130:218
复制代码

3.4. 主启动类

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

3.5. 业务类

    package com.atguigu.springcloud.config;
    
    @Configuration
    public class ApplicationContextConfig {
    
        @Bean
        @LoadBalanced //开启默认的负载均衡机制:赋予了RestTemplate负载均衡的能力
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    }
  
    package com.atguigu.springcloud.controller; 
    
    @RestController
    @Slf4j
    public class OrderZKController {
    
        //由于在ApplicationContextConfig开启了负载均衡,这里可以通过服务名访问到微服务
        public static final  String INVOKE_URL = "http://cloud-provider-payment";
    
        @Resource
        private RestTemplate restTemplate;
    
        //返回String测试一下:不交互数据库了
        @GetMapping("/consumer/payment/zk")
        public String paymentInfo(){
            String result = restTemplate.getForObject(INVOKE_URL+"/payment/zk", String.class);
    
            return result;
        }
    }
复制代码

3.6. 测试

    1.  服务注册进zookeeper成功
复制代码

img

    2.  服务调用成功
复制代码

img

4 Consul 服务注册与发现

4.1 Consul 简介

1.  是什么:微服务的服务注册中心
复制代码

官网

    Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorp公司采用Go语言开发
    
    提供了微服务系统中心的服务治理,配置中心,控制总线等功能。这些功能中的每一个都可以根据需要
    单独使用,也可以一起使用,以构建全方位的服务网格。
    
    总之Consul提供了一种完整的服务网格解决方案。
    
    它具有很多优点:
        包括,基于raft协议,比较简洁;支持健康检查,同时支持HTTP和DNS协议支持跨数据中心的WAN集群。
        
        提供图形界面 跨平台,支持Linux,MAC,Windows

2.  能干嘛:The key features of Consul are:

        Service Discovery:服务发现,提供HTTP和DNS两种发现方式
        
        Health Checking: 健康检查,支持多种方式,HTTP,TCP,Docker,Shell脚本定制化
        
        KV Store:   Key,Value的存储方式
        
        Secure Service Communication: 安全的服务交流
        
        Multi Datacenter:多数据中心
        
        可视化web界面
        
        
3.  下载
复制代码

下载

4.  怎么用
复制代码

中文文档

4.2 安装并运行 Consul

    1.  下载完成后只有一个consul.exe文件
        
        硬盘路径下双击运行
    
    2.  cmd:
        查看版本:   D:\Developer_Tools\Consul>consul --version
        
        使用开发者模式启动:  D:\Developer_Tools\Consul>consul agent -dev
        
    3.  可视化web页面:localhost:8500
复制代码

img

5. 生产者服务注册:consul

5.1 新建 Module 支付服务:cloud-providerconsul-payment8006

5.2 pom

<dependencies>
        <!--consul和SpringCloud的整合-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--引入我们自定义的公共api jar包-->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--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>

        <!--Mybatis和SpringBoot的整合-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <!--如果没写版本,从父层面找,找到了就直接用,全局统一-->
        </dependency>

        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>
复制代码

5.3 yml

    # 微服务端口号
    server:
      port: 8006
    
    # 微服务名称
    spring:
      application:
        name: cloud-provider-payment
    
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource      # 数据源
        driver-class-name: com.mysql.cj.jdbc.Driver     # mysql驱动包
        url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: root
      cloud:
        consul:
          host: localhost
          port: 8500
          discovery:
            service-name: ${spring.application.name}
    
    
    
    mybatis:
      mapper-locations: classpath:mapper/*.xml                # 扫描类路径下mapper文件夹下的.xml配置文件
      type-aliases-package: com.atguigu.springcloud.entities  # 该包所有Entity类,取默认别名
复制代码

5.4 主启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class PaymentMain8006 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8006.class, args);
        }
    }
复制代码

5.5 controller

    @RestController
    @Slf4j
    public class PaymentController {
    
        @Value("${server.port}")
        private String serverPort;
    
        @RequestMapping(value="/payment/consul")
        public String paymentConsul(){
            return "springcloud with consul: "+serverPort+"\t"+ UUID.randomUUID().toString();
        }
    }
复制代码

5.6 测试

    启动8006服务
复制代码

img

    注册成功
复制代码

img

6. 消费者服务注册:consul

6.1 新建 module

新建module cloud-consumerconsul-order80
复制代码

6.2 pom

<dependencies>

        <!--consul和SpringCloud的整合-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--引入我们自定义的公共api jar包-->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--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>

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

复制代码

6.3 yml

    server:
      port: 80
    
    spring:
      application:
        name: cloud-consumer-order
    
      cloud:
        consul:
          host: localhost
          port: 8500
          discovery:
            service-name: ${spring.application.name}
复制代码

6.4 主启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class OrderConsulMain80 {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderConsulMain80.class, args);
        }
    }
复制代码

6.5 controller 和 config

config
复制代码
    @Configuration
    public class ApplicationContextConfig {
    
        @Bean
        @LoadBalanced //开启默认的负载均衡机制:赋予了RestTemplate负载均衡的能力
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    }
复制代码
controller
复制代码
    @RestController
    @Slf4j
    public class OrderConsulController {
    
        //由于在ApplicationContextConfig开启了负载均衡,这里可以通过服务名访问到微服务
        public static final  String INVOKE_URL = "http://consul-provider-payment";
    
        @Resource
        private RestTemplate restTemplate;
    
        //返回String测试一下:不交互数据库了
        @GetMapping("/consumer/payment/consul")
        public String paymentInfo(){
            String result = restTemplate.getForObject(INVOKE_URL+"/payment/consul", String.class);
    
            return result;
        }
    }
复制代码

6.6 启动测试

img

7. 三个注册中心的异同点

img

    CAP:理论
    
        Eureka主要保证高可用:AP
        
        Zookeeper/Consul主要保证数据的一致:CP
        
        
    web界面:
        Eureka/Consul都有一个web界面。
        Zookeeper只有一个linux客户端。
复制代码

7.1

    从CAP理论分析一下异同:
    
        Eureka主要满足AP
        
        Zookeeper/Consul主要满足CP
        
        C:Consistency 强一致性
        A:Avaliability 可用性
        P: Partition tolerance 分区容错性
        
            P在分布式中永远都要保证。
            所以要么是CP,要么是AP。
            三个只能占2个。
        
        CAP理论关注粒度是数据,而不是整体系统设计的角度。
        
    
    1.  最多只能同时较好的满足两个
    
        CAP理论的核心:一个分布式系统不可能同时很好的满足三个需求。因此根据CAP原理将
        NOSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类。
        
        CA:单点集群,满足一致性,可用性的系统,通常扩展性不强大。
        
        CP:满足一致性,分区容错性的系统,对数据一致性要求高,所以性能负担大。
            Zookeeper/Consul
            
            要求数据必须一致性。
        
        AP:满足可用性,分许容错性的系统,通常可能对一致性要求低一些。
            Eureka
            
            场景:商场,暂时不一致错一点没关系,只要能正常访问下单即可。
        
        Eureka通过设置一些属性,也可以通过牺牲高可用性实现一致性的要求。
            
    2.  分布式必须满足:P: Partition tolerance 分区容错性
复制代码
posted @ 2021-01-30 19:12  codeFiler  阅读(352)  评论(0编辑  收藏  举报