一、关于

Spring Cloud Zookeeper包含以下特性:

  • 服务发现:实例可以注册到Zookeeper,客户端可以使用spring管理的bean发现实例
  • 支持Spring Cloud LoadBalancer -客户端负载均衡解决方案
  • 支持Spring Cloud OpenFeign
  • 分布式配置:使用Zookeeper作为数据存储

本文代码仓库地址:https://github.com/lazyrabb1t/rabb-springcloud-demo

二、使用

2.1 创建提供者模块

2.1.1 引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-config</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-bootstrap</artifactId>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
2.1.2 配置

application.yml配置如下:

spring:
  application:
    name: rabb-zookeeper-provider
  cloud:
    zookeeper:
      connect-string: localhost:2181
server:
  port: 20100
2.1.3 添加远程接口
@SpringBootApplication
@RestController
@Slf4j
public class ZookeeperProviderApplication {

    @Value("${server.port}")
    String port;

    public static void main(String[] args) {
        SpringApplication.run(ZookeeperProviderApplication.class, args);
    }

    @GetMapping
    public String hello() {
        log.info("调用提供者hello接口");
        return "Hello SpringCloud! from port:" + port;
    }
}

2.2 创建消费者模块

2.2.1 添加依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
2.2.2 配置

application.yml配置如下:

server:
  port: 20101
spring:
  config:
    import: 'optional:zookeeper:'
  application:
    name: rabb-zookeeper-consumer
  cloud:
    zookeeper:
      connect-string: localhost:2181
service-url:
  provider: http://rabb-zookeeper-provider
2.2.3 注册restTemplate
@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
2.2.4 添加接口测试服务远程调用以及配置获取
@SpringBootApplication
@RestController
@Slf4j
@EnableConfigurationProperties
public class ZookeeperConsumerApplication {

    @Autowired
    RestTemplate restTemplate;
    @Value("${service-url.provider}")
    String providerService;
    // 从配置中心获取的配置
    @Value("${url}")
    String url;

    public static void main(String[] args) {
        SpringApplication.run(ZookeeperConsumerApplication.class, args);
    }

    @GetMapping
    public String hello() {
        log.info("调用消费者hello接口");
        return "INVOKE PROVIDER HELLO METHOD:" + restTemplate.getForEntity(providerService, String.class).getBody();
    }

    @GetMapping("url")
    public String url() {
        return url;
    }
}
2.2.5 动态获取配置

直接通过@Value注解获取的配置无法自动刷新,我们可以通过@ConfigurationProperties注解来动态获取配置:

/**
 * 支持动态刷新配置
 */
@Component
@ConfigurationProperties(prefix = "rabb")
public class ZookeeperConfig {
    public String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

注入ZookeeperConfig来获取配置:

@RestController
@Slf4j
public class ConfigController {

    @Autowired
    ZookeeperConfig zookeeperConfig;

    @GetMapping("url2")
    public String url2() {
        return zookeeperConfig.getUrl();
    }
}

2.3 启动Zookeeper

2.3.1 启动
2.3.2 添加配置

2.2.4以及2.2.5中,我们获取了名为url以及rabb.url的参数,因此我们需要在Zookeeper中手动创建这两项配置,命令如下:

# 通过ZkCli创建节点
create /config
create /config/rabb-zookeeper-consumer
create /config/rabb-zookeeper-consumer/rabb
create /config/rabb-zookeeper-consumer/url "https://lazyrabbit.xyz"
create /config/rabb-zookeeper-consumer/rabb/url "https://www.lazyrabbit.xyz"

默认所有配置都在/config目录下,然后第二级目录为应用的名称(rabb-zookeeper-consumer)以及对应的环境配置(如果有则默认逗号分割),之后就是变量的名称了,如变量名称为rabb.url对应在Zookeeper的路径为/rabb/url,整个拼接起来就是/config/rabb-zookeeper-consumer/rabb/url,然后路径对应的data就是值,可以参考官网的说明:https://docs.spring.io/spring-cloud-zookeeper/docs/current/reference/html/#spring-cloud-zookeeper-config

同时,也可以进行配置,如下:

spring:
  cloud:
    zookeeper:
      config:
        enabled: true
        # 根目录,默认config
        root: configuration
        # 设置所有应用程序使用的名称
        defaultContext: apps
        # 设置环境配置的分隔符
        profileSeparator: '::'

2.4 测试

启动消费者与提供者,消费者可以通过服务名称调用提供者的接口,同时消费者也可以动态获取Zookeeper中的配置

2.5 引入外部配置数据的新方式

在之前的版本中要通过配置中心来获取配置的时候,我们需要引入spring-cloud-starter-bootstrap依赖,并使用bootstrap配置文件。

在Spring Boot 2.4版本中,可以通过spring.config.import属性来导入配置数据。这也是从Zookeeper获取配置的默认方式,配置如下:

spring:
  config:
    import: 'optional:zookeeper:'

同时也可以在该属性中配置Zookeeper的连接地址以及指定配置路径,如:optional:zookeeper:myhost:2181/contextone;/context/two

官方文档:https://docs.spring.io/spring-cloud-zookeeper/docs/current/reference/html/#config-data-import