服务注册(ServiceRegistry)与发现(DiscoveryClient)在Spring Cloud中都进行了抽象。除了之前介绍的Eureka外,Spring Cloud也支持使用Zookeeper作为服务的注册中心。基于Zookeeper的服务注册由org.springframework.cloud.zookeeper.serviceregistry.ZookeeperServiceRegistry
实现,服务发现由org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryClient
实现。需要使用Zookeeper进行服务注册与发现时需要加入spring-cloud-starter-zookeeper-discovery
依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
spring-cloud-starter-zookeeper-discovery
默认会使用的是基于Zookeeper3.5.X系列的jar包,如果你使用的是Zookeeper3.4.X系列,则需要自己手动的指定依赖Zookeeper3.4.X系列,同时在spring-cloud-starter-zookeeper-discovery
中排除对Zookeeper的依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-all</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.12</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
通常作为服务提供方的应用都是Web应用,所以一般还需要加上spring-boot-starter-web
依赖。Classpath中添加了spring-cloud-starter-zookeeper-discovery
后Spring Cloud默认会把自己注册到地址为localhost:2181
的zookeeper,服务名称默认取${spring.application.name}
,如果没有指定spring.application.name
则默认取application
。注册时会在/services/serviceId
下写入实例信息,比如serviceId指定为service1
,则默认会在/services/service1
目录下创建一个实例对应的节点,写入实例信息。如果你需要连接的Zookeeper的地址不是localhost:2181
,则可以通过spring.cloud.zookeeper.connectString
进行指定。
spring:
application:
name: service1
cloud:
zookeeper:
connect-string: 10.10.10.1:2181
无论是服务提供者还是客户端应用都需要添加spring-cloud-starter-zookeeper-discovery
依赖。服务提供方应用按照上面的配置就已经可以了。客户端应用,如果你使用Feign,则需要添加spring-cloud-starter-openfeign
依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
然后声明@FeignClient
,定义对远程接口的抽象,比如下面这样。
@FeignClient("${feign.service1.name:service1}")
public interface HelloService {
@GetMapping("hello")
String hello();
}
然后在@Configuration
类上声明@EnableFeignClients
以启用对Feign的支持,并将扫描@FeignClient
。
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
FeignClient将通过@FeignClient
上指定的serviceId到Zookeeper上寻找对应的实例,从而完成相应的调用。
对于客户端应用而言,如果它只作为客户端,而不需要对外提供服务,或者说它不需要作为一个服务注册到Zookeeper中,则我们可以指定spring.cloud.service-registry.auto-registration.enabled=false
或者spring.cloud.zookeeper.discovery.register=false
。
spring:
cloud:
service-registry:
auto-registration:
enabled: false
如果我们的应用中拥有spring-cloud-starter-zookeeper-discovery
,但是我们又不想使用基于Zookeeper的服务发现与注册功能,则可以指定spring.cloud.zookeeper.enabled=false
,如果只是不想使用服务发现功能,则可以指定spring.cloud.zookeeper.discovery.enabled=false
。Spring Cloud Zookeeper不允许我们只启用服务注册功能,而不启用服务发现功能。换言之,启用服务注册功能的前提是启用了服务发现功能。所以如果你的服务提供方不需要依赖其它服务,但是它需要作为一个服务注册到Zookeeper上,你不能指定spring.cloud.zookeeper.discovery.enabled=false
。更多关于Spring Cloud Zookeeper可以指定的信息可以参考org.springframework.cloud.zookeeper.ZookeeperProperties
的源码或API文档。
服务注册到Zookeeper中默认写入的主机地址是主机名,很多时候可能你更希望它写入的是IP地址。此时可以指定spring.cloud.zookeeper.discovery.preferIpAddress=true
。
spring:
cloud:
zookeeper:
discovery:
prefer-ip-address: true
服务注册到Zookeeper中的实例ID默认是当前ApplicationContext的ID,它通常可以做到唯一,但是可读性不强。可能你更希望它能够表现为当前的主机跟端口,则可以指定spring.cloud.zookeeper.discovery.instanceId
为如下这样。
spring:
cloud:
zookeeper:
discovery:
instance-id: ${spring.cloud.client.hostname}:${server.port}
如果你希望instanceId是主机IP和端口的组合,则可以指定instanceId的值为
${spring.cloud.client.ip-address}:${server.port}
。
Spring Cloud Zookeeper在进行服务注册与发现时默认的namespace,或者说根路径是/services
,如果你使用的Zookeeper该路径已经有其它用途了,你可能想要更换这个根路径。可以通过spring.cloud.zookeeper.discovery.root
属性来更换这个根路径,比如下面就指定了根路径是/springcloud
。当更换了默认的根路径时,注意服务提供方和客户端都需要更换这个路径。
spring:
cloud:
zookeeper:
discovery:
root: /springcloud
Spring Cloud Zookeeper底层在与Zookeeper进行交互时使用的是Apache Curator,其会自动注册org.apache.curator.framework.CuratorFramework
类型的bean,所以如果应用中需要自己直接与Zookeeper进行交互时可以直接注入CuratorFramework
,然后通过它与Zookeeper进行交互。