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+"\t"+ 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原則,無主從節點,一個節點掛了,自動切換其他節點可以使用,去中心化。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM