zookeeper服務發現實戰及原理--spring-cloud-zookeeper分析

zookeeper服務發現實戰及原理--spring-cloud-zookeeper分析
1.原理html

1.1 zookeeper是什麼? java

  ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個爲分佈式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分佈式同步、組服務等。git

1.2 爲何zookeeper?github

  大部分分佈式應用須要一個主控、協調器或控制器來管理物理分佈的子進程(如資源、任務分配等)
  目前,大部分應用須要開發私有的協調程序,缺少一個通用的機制
  協調程序的反覆編寫浪費,且難以造成通用、伸縮性好的協調器
  ZooKeeper:提供通用的分佈式鎖服務,用以協調分佈式應用(如爲HBase提供服務)web

1.3 Zookeeper在微服務框架中能夠實現服務發現,該服務發現機制可做爲雲服務的註冊中心。spring

  經過Spring Cloud Zookeeper爲應用程序提供一種Spring Boot集成,將Zookeeper經過自動配置和綁定 的方式集成到Spring環境中apache

提早準備app

安裝zookeeper和zooinspector見框架

window7環境下ZooKeeper的安裝運行及監控查看dom

  這次安裝的zookeeper版本爲最新版

  zookeeper-3.5.4-beta 安裝過程同樣

  下載ZooInspector,參照指南運行java -Dfile.encoding=UTF-8 -jar zookeeper-dev-ZooInspector.jar便可

1.實戰

1.1 使用sts建立一個spring starter project名稱爲zk-discovery,以下圖所示

zookeeper服務發現實戰及原理--spring-cloud-zookeeper分析

此時自動生成的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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>zk-discovery</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zk-discovery</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <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.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

1.2 ZkDiscoveryApplication增長服務發現註解
@EnableDiscoveryClient

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

}

1.3 增長Rest服務HelloWorldController.java

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorldController {
    @GetMapping("/helloworld")
    public String HelloWorld() {
        return "Hello World!";
    }
}

1.4 配置屬性文件application.yml

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

2.源碼分析

以spring-boot app項目啓動時註冊服務ZookeeperAutoServiceRegistrationAutoConfiguration.java爲入口

@Bean
    @ConditionalOnMissingBean(ZookeeperRegistration.class)
    public ServiceInstanceRegistration serviceInstanceRegistration(
            ApplicationContext context, ZookeeperDiscoveryProperties properties) {
        String appName = context.getEnvironment().getProperty("spring.application.name",
                "application");
        String host = properties.getInstanceHost();
        if (!StringUtils.hasText(host)) {
            throw new IllegalStateException("instanceHost must not be empty");
        }

        ZookeeperInstance zookeeperInstance = new ZookeeperInstance(context.getId(),
                appName, properties.getMetadata());
        RegistrationBuilder builder = ServiceInstanceRegistration.builder() //1
          .address(host)   //2
                .name(appName)   //3
          .payload(zookeeperInstance) //4
                .uriSpec(properties.getUriSpec()); //5

        if (properties.getInstanceSslPort() != null) {
            builder.sslPort(properties.getInstanceSslPort());
        }
        if (properties.getInstanceId() != null) {
            builder.id(properties.getInstanceId());
        }

        // TODO add customizer?

        return builder.build();
    }

2.2 建立ServiceInstance的builder

/**
     * Return a new builder. The {@link #address} is set to the ip of the first
     * NIC in the system. The {@link #id} is set to a random UUID.
     *
     * @return builder
     * @throws Exception errors getting the local IP
     */
    public static<T> ServiceInstanceBuilder<T>builder() throws Exception
    {
        String                  address = null;
        Collection<InetAddress> ips = ServiceInstanceBuilder.getAllLocalIPs();
        if ( ips.size() > 0 )
        {
            address = ips.iterator().next().getHostAddress();   // default to the first address
        }

        String                  id = UUID.randomUUID().toString();

        return new ServiceInstanceBuilder<T>().address(address).id(id).registrationTimeUTC(System.currentTimeMillis());
    }

觀察zookeeper的生成狀況

zookeeper服務發現實戰及原理--spring-cloud-zookeeper分析

生成的helloWorld的服務信息以下:

{
  "name": "HelloWorld",
  "id": "ef95204e-f5e8-4c69-96e4-3f7cec8dce33",
  "address": "DESKTOP-405G2C8",
  "port": 8081,
  "sslPort": null,
  "payload": {
    "@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
    "id": "application-1",
    "name": "HelloWorld",
    "metadata": {

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

3.碰到的問題

Thrown "KeeperErrorCode = Unimplemented for /services" exception

  緣由:Curator 和zookeeper的版本不一致

  解決方式:zookeeper升級到最新的版本後異常消失

4.Spring Cloud中的Eureka和Zookeeper的區別

zookeeper服務發現實戰及原理--spring-cloud-zookeeper分析

對於 zookeeper 來書,它是 CP 的。也就是說,zookeeper 是保證數據的一致性的。

Eureka 在設計時優先保證可用性,這就是 AP 原則。Eureka 各個節點都是平等的,幾個節點掛掉不會影響正常節點的工做,剩餘的節點依然能夠提供註冊和查詢服務。

參考文獻

【1】https://cloud.spring.io/spring-cloud-zookeeper/1.2.x/multi/multi_spring-cloud-zookeeper-discovery.html

【2】https://cloud.spring.io/spring-cloud-zookeeper/1.2.x/multi/multi_spring-cloud-zookeeper-config.html

【3】http://www.enriquerecarte.com/2017-07-21/spring-cloud-config-series-introduction

【4】https://dzone.com/articles/spring-cloud-config-series-part-2-git-backend

【5】https://dzone.com/articles/spring-cloud-config-part-3-zookeeper-backend

【6】https://github.com/santteegt/spring-cloud-zookeeper-service-discovery-demo

【7】https://blog.csdn.net/peterwanghao/article/details/79722247

【8】https://www.cnblogs.com/EasonJim/p/7613734.html

【9】https://blog.csdn.net/eson_15/article/details/85561179

相關文章
相關標籤/搜索