Spring Cloud Zookeeper
这个项目主要为了实现通过自动配置方式将Zookeeper与Spring Boot应用进行集成,并绑定到Spring Environment以及其他Spring环境中。 通过一些简单的注解就可以快速的启用并配置出一个基于Zookeeper的大型分布式系统。 由此提供服务发现以及分布式配置服务。 而智能路由(Zuul),客户端负载均衡(Ribbon),断路器(Hystrix)等,还是继续由Spring Cloud Netflix提供。
9.1 Install Zookeeper
Zookeeper的安装,请参见
9.2 Service Discovery with Zookeeper
基于Zookeeper的服务发现
服务发现是微服务架构的关键概念。手动为每一个客户端配置一些链接是非常非常的繁琐的。 (Zookeeper的一个Java客户端类库)通过一个提供了服务发现服务。 Spring Cloud Zookeeper通过这个扩展包实现了服务注册和发现服务。
9.2.1 How to activate
引入
org.springframework.cloud:spring-cloud-starter-zookeeper-discovery
依赖,就可以自动启用Spring Cloud Zookeeper发现服务。
9.2.2 Registering with Zookeeper
当客户端通过Zookeeper进行注册时,需要提供一些关于自身的元数据,如:主机名,端口,id以及名称等。
Zookeeper客户端示例:
@SpringBootApplication@EnableDiscoveryClient@RestControllerpublic class Application { @RequestMapping("/") public String home() { return "Hello world"; } public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); }}
就是一个很普通的Spring Boot 应用。 如果Zookeeper部署在
localhost:2181
,那需要进行一些配置来指定Zookeeper。例如:
application.yml
spring: cloud: zookeeper: connect-string: localhost:2181
警告: 如果要使用,那相关配置就需要配置在bootstrap.yml
,而不是application.yml
。
默认的服务名,实例ID以及端口号,会从
Environment
中来获得,分别是${spring.application.name}
、Spring Context ID以及${server.port}
。
@EnableDiscoveryClient
注解可以让应用既作为一个Zookeeper的服务(因为这样会注册应用自身),也同时作为一个客户端(可通过Zookeeper寻找到其他服务)
9.2.3 Using the DiscoveryClient
Spring Cloud支持Feign,也支持Spring的RestTemplate通过一个逻辑服务名来替代物理URL。
可以使用
org.springframework.cloud.client.discovery.DiscoveryClient
提供的API来为非Netflix应用提供服务发现接口。例如:
@Autowiredprivate DiscoveryClient discoveryClient;public String serviceUrl() { Listlist = discoveryClient.getInstances("STORES"); if (list != null && list.size() > 0 ) { return list.get(0).getUri().toString(); } return null;}
9.3 Zookeeper Dependencies
9.3.1 Using the Zookeeper Dependencies
Spring Cloud Zookeeper 提供了应用所需的相关依赖。 通过依赖可以清晰的知道哪些应用注册到ZK中,并且可以通过Feign或者
RestTemplate
进行调用。
还可以通过Zookeeper Dependency Watcher功能来控制相关依赖以及一些状态变化。
9.3.2 How to activate Zookeeper Dependencies
- 引入
org.springframework.cloud:spring-cloud-starter-zookeeper-discovery
就可以自动配置Spring Cloud Zookeeper相关依赖; - 可以配置
spring.cloud.zookeeper.dependencies
来加入更多配置; - 可以设置
spring.cloud.zookeeper.dependency.enabled
为false,关闭自动依赖(默认true)
9.3.3 Setting up Zookeeper Dependencies
通过下面这个例子来说明:
application.yml
spring.application.name: yourServiceNamespring.cloud.zookeeper: dependencies: newsletter: path: /path/where/newsletter/has/registered/in/zookeeper loadBalancerType: ROUND_ROBIN contentTypeTemplate: application/vnd.newsletter.$version+json version: v1 headers: header1: - value1 header2: - value2 required: false stubs: org.springframework:foo:stubs mailing: path: /path/where/mailing/has/registered/in/zookeeper loadBalancerType: ROUND_ROBIN contentTypeTemplate: application/vnd.mailing.$version+json version: v1 required: true
配置的根节点是
spring.cloud.zookeeper.dependencies
。 然后接下来,就一步一步的分析上面这个配置。
Aliases
从根节点往下的每一个配置,都是作为Ribbon的一个别名。 别名的名字就是已经实例化的
DiscoveryClient
、Feign
或者RestTemplate
的serviceId。
在上面的配置中,有两个别名:
newsletter
和mailing
。 例如,newsletter
使用Feign实现:
@FeignClient("newsletter")public interface NewsletterService { @RequestMapping(method = RequestMethod.GET, value = "/newsletter") String getNewsletters();}
Path
配置中的
path
属性表示着,注册在ZK中的位置。像之前提到过的Ribbon是基于URL的,因此并不符合path的要求。这也是为什么Spring Cloud Zookeeper使用别名作为映射节点。
Load balancer type
配置中的
loadBalancerType
属性表示着,调用这个节点时所采用的负载均衡策略。可以在下列值中选择一个:
- STICKY 长用(一直请求这个节点)
- RANDOM 随机
- ROUND_ROBIN 循环调用(排队)
Content-Type template and version
配置中的
contentTypeTemplate
以及version
属性。 当应用API通过Content-Type
头来传递版本信息时,如果每次请求都手工配置肯定不好,而且当接口升级时如果还要重新编码制定版本信息也是极其低效的。所以,提供contentTypeTemplate
并配有$version
占位符,这样再配合version
属性,就可以灵活的通过配置信息来指定版本信息了。例如,有一个这样的contentTypeTemplate
:
application/vnd.newsletter.$version+json
以及
version
:
v1
那么,每一个请求的
Content-Type
就会自动设置为:
application/vnd.newsletter.v1+json
Default headers
配置中的
headers
属性,是一个map结构。 有的时候,需要在每一次请求中设置一些头部信息。而这些,都可以通过headers
属性,在配置文件中进行配置,而不需要代码。例如:
headers: Accept: - text/html - application/xhtml+xml Cache-Control: - no-cache
这样就会在每一个HTTP请求的头部中加入
Accept
和Cache-Control
。
Obligatory dependencies
配置中的
required
属性。 这个配置可以指定在应用启动时,某个服务是不是必须要有的。
如果设置为
true
,那应用启动时,如果应用不能发现服务则直接抛出异常,并且Spring Context启动失败。
更多细节会在后续的Spring Cloud Zookeeper Presence Checker部分介绍。
Stubs
可以配置一个用冒号分割的信息用于指定本地存根(用于本地逻辑,降级,默认行为等)。例如:
stubs: org.springframework:foo:stubs
其中具体含义为:
- groupId :
org.springframework
- artifactId :
foo
- classifier :
stubs
默认值
所以,这也等价于:
stubs: org.springframework:foo
9.3.4 Configuring Spring Cloud Zookeeper Dependencies
这部分主要是包含一组开关,用以控制Zookeeper特性。
- spring.cloud.zookeeper.dependencies 如果不想使用Zookeeper Dependencies功能,那就不要配置(废话 ^_^)
- spring.cloud.zookeeper.dependency.ribbon.enabled (默认开启)可以配置Ribbon全局或者对某一个服务进行单独配置。
- spring.cloud.zookeeper.dependency.ribbon.loadbalancer (默认开启)结合上面属性一起用的,可以配置运行时的负载均衡策略(
loadBalancerType
),必要时,还可以自定义LoadBalancerClient
、ILoadBalancer
来自定义负载均衡策略。如果不开启此配置,那注册应用除了path外,就没啥意义了。 - spring.cloud.zookeeper.dependency.headers.enabled (默认开启)控制着是否自动在请求头部加入信息。可以对诸如
RibbonClient
的每一次请求起作用。 - spring.cloud.zookeeper.dependency.resttemplate.enabled (默认开启)类似上一个配置,控制着请求头信息。让带有
@LoadBalanced
注解的RestTemplate
类,能够通过头信息进行负载。
9.4 Spring Cloud Zookeeper Dependency Watcher
Dependency Watcher机制允许通过对节点注册监听器。这个特性实际上就是个Observator模式。当相关节点状态发生变化时,可以执行一些自定义逻辑。
9.4.1 How to activate
Spring Cloud Zookeeper Dependencies会开启Dependency Watcher机制
9.4.2 Registering a listener
监听器需要实现
org.springframework.cloud.zookeeper.discovery.watcher.DependencyWatcherListener
接口,并注册Bean到Spring容器中。这个接口主要就是一个方法
void stateChanged(String dependencyName, DependencyState newState);
如果需要对一个特定的节点进行监听,可以通过
dependencyName
进行鉴别。newState
则提供节点的CONNECTED
或者DISCONNECTED
的节点状态变化。
9.4.3 Presence Checker
基于上面的Dependency Watcher机制,Presence Checker提供了在应用启动时检查某些节点的状态能力。
主要抽象成
org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier
以及org.springframework.cloud.zookeeper.discovery.watcher.presence.DefaultDependencyPresenceOnStartupVerifier
两个类来实现。工作方式如下:
- 如果节点配置成
required
,而ZK中并没有注册信息,则抛出异常,应用退出; - 如果节点配置为非
required
,那org.springframework.cloud.zookeeper.discovery.watcher.presence.LogMissingDependencyChecker
会记录一个WARN
级别的日志,应用正常启动。
当自定义
DefaultDependencyPresenceOnStartupVerifier
被注册,且没有DependencyPresenceOnStartupVerifier
时,可以对上述逻辑进行自定义。
9.5 Distributed Configuration with Zookeeper
Zookeeper提供了一个,运行客户端在其下存储数据,例如配置信息。 Spring Cloud Zookeeper Config就是一个可选的。 配置信息可以在启动时加载到Spring Environment中。配置信息默认存放在
/config
命名空间下。基于应用名称以及环境配置,会按照Spring Cloud Config的顺序创建多个PropertySource
实例。 Config。例如,应用名为“testApp”,环境“dev”,则下列配置源会被创建:
- config/testApp,dev
- config/testApp
- config/application,dev
- config/application
最为具体的配置源放在最上面,最泛化的放在最下面。
config/application
命名空间下的属性会被用于所有应用。config/testApp
命名空间下的属性只会被“testApp”服务的实例使用。
9.5.1 How to activate
只需要引入
org.springframework.cloud:spring-cloud-starter-zookeeper-config
就可以自动配置并启用Spring Cloud Zookeeper Config。
9.5.2 Customizing
Zookeeper Config可以通过下面的配置进行定制化:
bootstrap.yml
spring: cloud: zookeeper: config: enabled: true root: configuration defaultContext: apps profileSeparator: '::'
- enabled 是否启用Zookeeper Config的开关
- root 指定命名空间的根节点
- defaultContext 设置所有应用的默认命名空间
- profileSeparator 用于设置环境配置的分隔符