• Springcloud用Zookeeper做注册中心&CAP原则


      Springcloud用Zookeeper做注册中心。需要先安装好zookeeper。

    1. 支付模块用zookeeper做注册中心

    1新建支付模块 cloud-providerzk-payment8084

    选择父工程之后新建moudle,GroupId和Version采用继承的即可,如下:

     2.修改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>cloud</artifactId>
            <groupId>cn.qz.cloud</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>cloud-providerzk-payment8084</artifactId>
    
        <dependencies>
            <!-- SpringBoot整合zookeeper客户端 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            </dependency>
            <!--引入自己抽取的工具包-->
            <dependency>
                <groupId>cn.qz.cloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</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>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
    </project>

    3.新建yml配置文件:

    #8084表示注册到zookeeper服务器的支付服务提供者端口号
    server:
      port: 8084
    
    #服务别名----注册zookeeper到注册中心名称
    spring:
      application:
        name: cloud-provider-payment
      cloud:
        zookeeper:
          connect-string: 127.0.0.1:2181

    4.新建启动类:

    package cn.qz.cloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 22:49 2020/10/14
     */
    @SpringBootApplication
    @EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
    public class PaymentMain8084 {
    
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8084.class, args);
        }
    }

    5.新建测试Controller

    package cn.qz.cloud.controller;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.UUID;
    
    
    @RestController
    @RequestMapping("/pay")
    @Slf4j
    public class PaymentController
    {
        @Value("${server.port}")
        private String serverPort;
    
        @RequestMapping(value = "/paymentzk")
        public String paymentzk()
        {
            return "springcloud with zookeeper: "+serverPort+"	"+ UUID.randomUUID().toString();
        }
    }

    6.启动服务后查看zookeeper中注册的服务

     是在zookeeper建立了一个/services/appname/UUID这样的节点来存放数据,节点值格式化后如下:

    {
        "name": "cloud-provider-payment",
        "id": "ae024e43-703b-4edc-8a73-2cb7758fdb35",
        "address": "root",
        "port": 8084,
        "sslPort": null,
        "payload": {
            "@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
            "id": "application-1",
            "name": "cloud-provider-payment",
            "metadata": {}
        },
        "registrationTimeUTC": 1602687210606,
        "serviceType": "DYNAMIC",
        "uriSpec": {
            "parts": [
                {
                    "value": "scheme",
                    "variable": true
                },
                {
                    "value": "://",
                    "variable": false
                },
                {
                    "value": "address",
                    "variable": true
                },
                {
                    "value": ":",
                    "variable": false
                },
                {
                    "value": "port",
                    "variable": true
                }
            ]
        }
    }

    可以看到上面的zk注册中心的address是主机名称,改为IP:

    (1)修改yml文件:

    #8084表示注册到zookeeper服务器的支付服务提供者端口号
    server:
      port: 8084
    
    #服务别名----注册zookeeper到注册中心名称
    spring:
      application:
        name: cloud-provider-payment
      cloud:
        zookeeper:
          connect-string: 127.0.0.1:2181
          discovery:
            enabled: true
            instance-host: 127.0.0.1

    (2)启动后再次查看:

    {
        "name": "cloud-provider-payment",
        "id": "8f8a28b8-d154-469e-aef3-7073ebcad93b",
        "address": "127.0.0.1",
        "port": 8084,
        "sslPort": null,
        "payload": {
            "@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
            "id": "application-1",
            "name": "cloud-provider-payment",
            "metadata": {}
        },
        "registrationTimeUTC": 1602754345242,
        "serviceType": "DYNAMIC",
        "uriSpec": {
            "parts": [
                {
                    "value": "scheme",
                    "variable": true
                },
                {
                    "value": "://",
                    "variable": false
                },
                {
                    "value": "address",
                    "variable": true
                },
                {
                    "value": ":",
                    "variable": false
                },
                {
                    "value": "port",
                    "variable": true
                }
            ]
        }
    }

    (3)查看节点的属性如下:ephemeralOwner代表是临时节点,值为会话的ID

    2.订单模块调用zookeeper服务

    1.新建子模块:cloud-consumerzk-order80

     2.修改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>cloud</artifactId>
            <groupId>cn.qz.cloud</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>cloud-consumerzk-order80</artifactId>
    
        <dependencies>
            <!-- SpringBoot整合zookeeper客户端 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            </dependency>
            <!--引入自己抽取的工具包-->
            <dependency>
                <groupId>cn.qz.cloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</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>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
    </project>

    3.修改yml文件:

    server:
      port: 80
    
    spring:
      application:
        name: cloud-consumer-order
      cloud:
      #注册到zookeeper地址
        zookeeper:
          connect-string: 127.0.0.1:2181

    4.新建启动类:

    package cn.qz.cloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 23:05 2020/10/14
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    public class OrderZKMain80 {
        public static void main(String[] args) {
            SpringApplication.run(OrderZKMain80.class, args);
        }
    }

    5.建立业务类:

    (1)注册RestTemplate:

    package cn.qz.cloud.config;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class ApplicationContextConfig {
    
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplate() {
            return new RestTemplate();
        }
    }

    (2)Controller调用注册中心服务:

    package cn.qz.cloud.controller;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import javax.annotation.Resource;
    
    @RestController
    @RequestMapping("/consumer")
    public class OrderZKController {
        public static final String INVOKE_URL = "http://cloud-provider-payment";
    
        @Resource
        private RestTemplate restTemplate;
    
        @GetMapping("/pay/paymentzk")
        public String paymentzk() {
            String result = restTemplate.getForObject(INVOKE_URL + "/pay/paymentzk", String.class);
            return result;
        }
    }

    6.启动服务查看zk信息如下:

     7.访问测试结果如下:

    补充:Consul简介

      Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorp公司用Go语言开发。提供了服务治理、控制总线等功能。

      和zookeeper一样,需要安装客户端后使用。

    补充:Eureka、zk、Consul三个注册中心的异同点

    一张图如下:

    分布式环境有个CAP原则,又称为CAP理论,主要思想是在任何一个分布式系统中都无法同时满足CAP。

    C(Consistency):表示一致性,所有的节点同一时间看到的是相同的数据。

    A(Avaliablity):表示可用性,不管是否成功,确保一个请求都能接收到响应。

    P(Partion Tolerance):分区容错性,系统任意分区后,在网络故障时,仍能操作。

    (1)由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡。

    CA满足的情况下,P不能满足的原因:数据同步需要时间,也要正常的时间内响应(A),那么机器数量就要少,所以P就不满足

    CP 满足的情况下,A不能满足的原因:数据同步需要时间, 机器数量也多,但是同步数据需要时间,所以不能再正常时间内响应,所以A就不满足

    AP 满足的情况下,C不能满足的原因:机器数量也多,正常的时间内响应(A),那么数据就不能及时同步到其他节点,所以C不满足。

    (2)关于三个注册中心满足的原则:

    Zookeeper和Consul :CP设计,保证了一致性,集群搭建的时候,某个节点失效,则会进行选举行的leader,或者半数以上节点不可用,则无法提供服务,因此可用性没法满足。

    Eureka:AP原则,无主从节点,一个节点挂了,自动切换其他节点可以使用,去中心化。

  • 相关阅读:
    IT北漂攻略—择业篇(程序员.net)
    Log4net和Log2Console 结合使用时出现的中文问题
    日志设计规范
    IT北漂攻略租房篇
    Log2Console日志监测工具使用方法
    一些好用的开源控件
    工作流设计简介
    代码设计规范
    正则表达式分割字符串但是不分割字符串中引号中间的数据
    解决Android 应用运行报Unable to resolve superclass of L错误
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/13812227.html
Copyright © 2020-2023  润新知