整体架构
在分布式架构中,各模块采用多节点部署,对外提供服务,节点数量和服务地址不断会有变化,因此,对于服务调用者,需要动态获取服务地址。ZooKeeper 提供分布式协调服务,服务提供者可以将服务注册至ZooKeeper规定路径中,服务调用者再从ZooKeeper规定路径中动态发现服务,如图所示:
服务注册
Curator 进一步封装了ZooKeeper API,提供了许多高级功能,包括服务注册和发现。ZooKeeper使用版本3.4.6,Curator使用版本2.9.1,在pom.xml中增加Curator依赖,如下所示:1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>2.9.1</version>
</dependency>
使用Curator进行服务注册,代码如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/* 服务注册 start */
// 创建CuratorFramework实例,封装与ZooKeeper的操作。
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("xxx.xxx.xxx.xxx:2181", new RetryNTimes(4, 2000));
curatorFramework.start();
// 创建ServiceInstanceBuilder实例,指定服务名称和地址,
// 由ServiceInstanceBuilder实例构建ServiceInstance实例,ServiceInstance实例即服务。
ServiceInstanceBuilder serviceInstanceBuilder = ServiceInstance.builder();
serviceInstanceBuilder.uriSpec(new UriSpec("{scheme}://{address}:{port}"));
serviceInstanceBuilder.address("xxx.xxx.xxx.xxx");
serviceInstanceBuilder.port(8080);
serviceInstanceBuilder.name("service1");
ServiceInstance serviceInstance = serviceInstanceBuilder.build();
// 创建serviceDiscoveryBuilder实例,指定服务和服务在Zookeeper中所在路径,
// 由ServiceDiscoveryBuilder实例构建ServiceDiscovery实例,由ServiceDiscovery实例注册服务。
ServiceDiscoveryBuilder serviceDiscoveryBuilder = ServiceDiscoveryBuilder.builder(Void.class);
serviceDiscoveryBuilder.basePath("test");
serviceDiscoveryBuilder.client(curatorFramework);
ServiceDiscovery serviceDiscovery = serviceDiscoveryBuilder.build();
serviceDiscovery.start();
//注册服务
serviceDiscovery.registerService(serviceInstance);
/* 服务注册 end */
// 等待30秒,这时在ZooKeeper中可以查看到注册的服务
Thread.sleep(30000);
// 30秒后,进程关闭,ZooKeeper中注册的服务因是临时节点而被删除,说明服务已不可用
启动进程,在ZooKeeper中可以查看到注册的服务,在服务“service1”所在路径“/test/service1”下有一个临时节点“ffd66440-e0b0-41a5-b93a-c558c527b3bc”,表示刚启动、注册的服务,如图所示:
30秒后进程关闭,在ZooKeeper中可以查看到,注册的服务因是临时节点而被删除,说明服务已不可用,如图所示:
服务发现
调用ServiceDiscovery实例的queryForInstances方法可以发现服务,代码如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/* 服务发现 start */
// 创建CuratorFramework实例,封装与ZooKeeper的操作。
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("xxx.xxx.xxx.xxx:2181", new RetryNTimes(4, 2000));
curatorFramework.start();
// 创建serviceDiscoveryBuilder实例,指定服务在Zookeeper中所在路径,
// 由ServiceDiscoveryBuilder实例构建ServiceDiscovery实例,由ServiceDiscovery实例发现服务。
ServiceDiscoveryBuilder serviceDiscoveryBuilder = ServiceDiscoveryBuilder.builder(Void.class);
serviceDiscoveryBuilder.basePath("test");
serviceDiscoveryBuilder.client(curatorFramework);
ServiceDiscovery serviceDiscovery = serviceDiscoveryBuilder.build();
serviceDiscovery.start();
Collection<ServiceInstance> collection = serviceDiscovery.queryForInstances("service1");
if (collection != null && collection.size() > 0) {
System.out.println("found " + collection.size() + " service1 services");
for (ServiceInstance serviceInstance : collection) {
System.out.println("id: " + serviceInstance.getId());
}
}
/* 服务发现 end */
启动进程,发现服务,如图所示: