目前微服务SpringCloud使用的注册中心有Eureka、Zookeeper、Consul等,本文来上手一波Zookeeper!
1.Zookeeper的安装
这里采用的是在Aliyun云服务器ECS、Ubuntu上安装。
1.0 说明:这里必须提前安装JDK,可以参照网上的教程。
1.1 使用wget下载Zookeeper(如果你从其他地方下载Zookeeper,换个链接即可)
wget https://mirrors.bfsu.edu.cn/apache/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz --no-check-certificate
1.2 使用tar命令解压缩
sudo tar -zxvf apache-zookeeper-3.6.2-bin.tar.gz
1.3 进入配置文件夹,并拷贝配置文件
# 进入配置文件夹
cd apache-zookeeper-3.6.2-bin/conf/
# 拷贝配置文件(必须拷贝为zoo.cfg才能启动,Zookeeper的more配置文件为这个)
cp zoo_sample.cfg zoo.cfg
1.4 添加环境变量
#编辑配置文件
vim ~/.profile
#在配置文件最后添加环境变量,下面/root/apache-zookeeper-3.6.2-bin/bin改为自己的Zookeeper的bin目录
export PATH=/root/apache-zookeeper-3.6.2-bin/bin:$PATH
#使配置文件生效
source ~/.profile
1.5 在安全组中开放2181端口,并保证8080端口没有被占用!!!!!
1.6 使用zkServer.sh start
命令启动Zookeeper服务
下面附加一些常见的命令:
//zookeeper 常用服务命令
//可以不在bin目录下运行,因为我们已经配置了环境变量,可以全局访问
zkServer.sh start 启动
zkServer.sh status 查看状态
zkServer.sh stop 停止/关闭
1.7 使用zkCli.sh
命令进入Zookeeper的客户端
2.既然使用了SpringCloud,我们就要使用SpringCloud去在Zookeeper中注册服务
我这里使用的是2021-02-01当前最新的SpringBoot(2.4.2)和SpringCloud最新版,注意这里的jar包要对照官网来引入,SpringBoot和SpringCloud版本有对应关系。
2.1 编写Provider(服务提供者)模块
引入maven依赖(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 https://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.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wanna</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.0</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>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<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>
<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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
注意:这个Zookeeper的jar包可能和你的Zookeeper服务器的版本不同!因此,需要排除自带的zookeeper依赖,自己去引入对应版本的依赖(一定要对应)
排除依赖:
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
引入3.6.2依赖:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.2</version>
</dependency>
编写application.yaml
我们改变了tomcat的端口号为8001,这个项目的应用名为cloud-provider-payment8001,并且指定了xx.xx.xx.xx:2181为我们Zookeeper服务器的IP和端口
server:
port: 8001
spring:
application:
name: cloud-provider-payment8001
cloud:
zookeeper:
connect-string: xx.xx.xx.xx:2181
编写主启动类:
package com.wanna.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SpringcloudApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudApplication.class, args);
}
}
需要注意的是,我们需要加上@EnableDiscoveryClient
注解表示我们这是一个服务发现的客户端!
编写Controller
package com.wanna.springcloud.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PaymentController {
@RequestMapping("/payment")
public String payment(){
return "payment8001";
}
}
就是我们一个正常的controller而已~
2.2 编写Consumer(消费者)模块
引入maven依赖
<?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 https://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.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wanna</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.0</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<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>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<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>
<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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
这里,和Provider类似!
编写application.yaml,这里也和Provider类似
server:
port: 80
spring:
application:
name: cloud-consumer-order80
cloud:
zookeeper:
connect-string: xx.xx.xx.xx:2181
编写主启动类,也和Provider类似
package com.wanna.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SpringcloudApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudApplication.class, args);
}
}
编写Controller,INVOKE_URL就是我们要调用的服务的Http链接,调用的是"/payment"路径下的服务,但是它接收的是"/consumer/payment"的请求(80服务),也就是说我们想在浏览器通过http://localhost/consumer/payment就请求到Provider中的Controller中的数据,实现微服务的调用!
package com.wanna.springcloud.controller;
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
public class OrderController {
public static final String INVOKE_URL = "http://cloud-provider-payment8001";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/payment")
public String paymentInfo() {
String result = restTemplate.getForObject(INVOKE_URL + "/payment",String.class);
return result;
}
}
这里用到了RestTemplate,我们就应该生产一个这样一个bean,编写配置类:
package com.wanna.springcloud.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 GetTemplate(){
return new RestTemplate();
}
}
3. 测试Provider和Consumer在服务器上是否被注册?
先启动Provider,在Ubuntu上使用zkCli.sh命令进入客户端,使用ls /services查看已经注册的服务!
- ls /services
- [cloud-provider-payment8001]
- ls /services/cloud-provider-payment8001
- [dea4bf08-f0aa-4a85-a85b-69719fdeb3d7]
//获取Zookeeper的Znode结点
- ls /services/cloud-provider-payment8001/dea4bf08-f0aa-4a85-a85b-69719fdeb3d7
- []
//获取到我们注册的相关信息
- get /services/cloud-provider-payment8001/dea4bf08-f0aa-4a85-a85b-69719fdeb3d7
- {"name":"cloud-provider-payment8001","id":"dea4bf08-f0aa-4a85-a85b-69719fdeb3d7","address":"192.168.191.110","port":8001,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"cloud-provider-payment8001","name":"cloud-provider-payment8001","metadata":{"instance_status":"UP"}},"registrationTimeUTC":1612201061275,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}
注册服务成功!
尝试启动Consumer
- ls /services
- [cloud-consumer-order80, cloud-provider-payment8001]
注册成功!
那么服务消费者Consumer能否调用Provider呢?调用成功!我们发现,我们启动的是80端口的服务,但是调用了8001端口的服务!

折腾成功!!最重要的就是maven的jar包的情况,我们一定要注意jar包有没有冲突,有没有报错,一旦报错,可能项目就启动不起来,服务也不能在Zookeeper中注册成功!最主要注意的是Boot和Cloud的版本对应(得看官网,这个不能乱搞,乱搞就是作死)!
网友评论