简介
内容来源:链接 这是Eureka的替代方案,因为Eureka没更新了。 这个方案的搭建过程和Eureka一样方便。 尤其是服务集群的搭建,非常适合动态水平扩展,我觉得这点比 Eureka 强,因为 Eureka 需要配置 defaultZone 来指明各个集群服务器的地址,但是 Zookeeper 这个方案不需要修改配置文件,只要 spring.application.name 相同就被认为是同一个服务,然后集群服务设置不同端口就行了。
环境搭建
- 注意,客户端和服务端的搭建方式完全一样,没有任何不同。
- zookeeper整合springboot
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>2.3.0.RELEASE</spring.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
</dependencies>
spring:
application:
name: cloud-provider-payment
cloud:
zookeeper:
connect-string: 192.168.132.201:2181
可能出现的问题
org.apache.zookeeper.KeeperException$UnimplementedException: KeeperErrorCode = Unimplemented for 这个是由于使用的zookeeper版本过低导致的,可以升级zookeeper的版本,或者降低引入的引擎版本
<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.4.9</version>
</dependency>
服务中心的使用
节点信息的位置和含义
使用 zookeeper 客户端连接 zookeeper 会发现注册进去的服务变成了一个临时节点,连接的服务信息会被存储在 /services/{服务名}/{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
}
]
}
}
服务断连
- 一旦service宕机,zookeeper不会立马下线服务的节点,而是等待一段时间,一段时间过后仍旧断连的话,zookeeper 会删除该服务的临时节点。等到服务重新上线后,Zookeeper会重新生成一个临时服务节点。
服务调用
- 该功能让客户端和服务端都注册进 Zookeeper 中,客户端可以通过服务的项目名 + 接口名来调用到服务的接口
- 需要使用RestTemplate
package wu.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();
}
}
package wu.controller;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController
@RequestMapping
public class ServerController {
@Autowired
private RestTemplate restTemplate;
public static final String INVOKE_URL = "http://cloud-provider-server";
@GetMapping("/client")
public String test(){
String result = restTemplate.getForObject(INVOKE_URL+"/server",String.class);
return result;
}
}
服务集群
- 这里实现集群比较简单,比Eureka做的更方便。
- 就是完全拷贝服务项目,然后只更改端口号,其他什么都不变即可
- 因为 spring.application.name 是一致的,所以它们被 Zookeeper 认为是同一个服务,客户端可以通过相同的方式访问到,并且 RestTemplate 设置为负载均衡的话,可以平衡地访问两个服务。
- 使用 Docker 把服务项目生成一个镜像,然后在启动多个暴露不同端口的容器,这样实现集群是非常方便的。
|