1. Introduction

This article shows you how to use Zookeeper to implement service discovery in a microservices framework that acts as a registry for cloud services. Spring Cloud Zookeeper provides Spring Boot integration for applications, integrating Zookeeper into the Spring environment through automatic configuration and binding.

In this example we will create two applications:

  • The application that provides the service (calledService provider)
  • Applications that use this service (calledService consumer)

2. Install the Zookeeper

2.1 download

Apache is the official latest version: 3.4.8 download address: http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz

2.2 installation

CFG: change the zoo_sample. CFG file name (D:softzookeeper-3.4.8conf) to ‘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=1Copy the code
  • tickTime: Indicates the heartbeat interval between Zookeeper servers or between clients and servers. That is, each tickTime sends a heartbeat.
  • dataDir: Is the directory where Zookeeper saves data. By default, Zookeeper saves log files that write data in this directory.
  • dataLogDir: Indicates the directory where Zookeeper saves log files
  • clientPort: This port is used by the client to connect to the Zookeeper server. Zookeeper listens to this port and receives access requests from the client.

2.3 start

Go to the bin directory and start zkserver.cmd. This script will start a Java process. Double-click the file to start it:

3. Set up service providers

We will create a service provider by adding the Pring-Cloud-starter-Zookeeper-Discovery dependency and introducing the @enableDiscoveryClient annotation in the main program. The service returns “Hello World!” via a GET request. A string. The overall project structure is as follows:

3.1 Importing Dependencies

<? The 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 - the cloud - they are - proivder < / artifactId > < version > 1.0 - the SNAPSHOT < / version > < the parent > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> The < 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 supports SpringMVC for the Web, <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> <! <id> snapshots</id> snapshots</ name> SpringCloud version --> <repository> <id> 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>Copy the code

3.2 start the class

Annotate our main class with @enableDiscoveryClient, which will cause the HelloWorld application to publish automatically.

package com.yiidian.provider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * service ProviderStarter class */ @springbootapplication @enablediscoveryclient public class ProviderStarter {public static void main(String[] args) { SpringApplication.run(ProviderStarter.class,args); }}Copy the code

3.3 the 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 * Controller */ @restController Public Class HelloController {@getMapping ("/hello") public String hello(){ return "Hello World"; }}Copy the code

3.4 configuration application. Yml

Yml defines the service name to be invoked by the client and configures Zookeeper information to register the service.

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

4. Build service consumers

Now let’s create a REST service consumer that uses the Spring Netflix Feign Client to invoke the service. Take a look at the overall project structure:

4.1 Importing Dependencies

Add dependency packages to the POM file.

<? The 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 - the cloud - they are - consumer < / artifactId > < version > 1.0 - the SNAPSHOT < / version > < the parent > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> The < 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 supports SpringMVC for the Web, <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> <! <id> snapshots</id> snapshots</ name> SpringCloud version --> <repository> <id> 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>Copy the code

4.2 start the class

Add the @enableDiscoveryClient annotation to the main program as with the service provider.

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; /** * service ConsumerStarter class */ @springbootapplication @enablediscoveryclient @enablefeignclients public class ConsumerStarter {public  static void main(String[] args) { SpringApplication.run(ConsumerStarter.class,args); }}Copy the code

4.3 Defining the Feign Remote Interface

By introducing the Spring-Cloud-starter-OpenFeign component package to invoke remote services using declarative service invocation, annotating an interface with @FeignClient (” service-name “) and automatically connecting it to our application, So that we can programmatically access the service.

package com.yiidian.consumer.client; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; /** * Feign remote interface */ @feignClient ("Provider") public interface HelloClient {@getMapping ("/hello") public String hello(); }Copy the code

4.4 the Controller

Here is a simple service controller class that consumes the service provider’s interface by injecting an interface helloWorldClient object to invoke the service provider’s interface and display its return value in the response.

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(); }}Copy the code

4.5 configuration 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
Copy the code

5. Test

The HelloWorld REST service registers itself in Zookeeper, and the Greeting service discovers and invokes the HelloWorld service through a declarative client.

Now we can run these two services, then visit http://localhost:9002/get-greeting in the browser, will return to the following information:

6. Summary

In this article, we saw how to implement service discovery using Spring Cloud Zookeeper and registered a service called Hello World in Zookeeper. A service consumer Greeting is then implemented through declarative service invocation to discover and consume the service.

By the way, the differences between Zookeeper and Eureka are introduced. The service governance mechanism implemented by Spring Cloud Eureka emphasizes AP, availability and reliability in THE CAP principle, while Zookeeper emphasizes CP (consistency and reliability). Had been in order to achieve a higher service availability, sacrifice a certain consistency, in extreme cases it would prefer to accept failure examples don’t lost a “healthy” as an example, for example, when disconnected service registry network is broken, because all of the service instance can’t keep contract heartbeat, with emphasis on the service governance CP will be out all service instance, Eureka, on the other hand, triggers a protection mechanism that preserves all nodes so that services can still call each other.

Welcome to pay attention to my public number: : a little tutorial. Get exclusive organized learning resources and daily dry goods push.

If you are interested in my series of tutorials, you can also check out my website: yiidian.com