5分钟了解[Apache]Curator Service Dis
2016-07-13 本文已影响896人
chesser
Curator Service Discovery要解决什么问题?
在SOA/分布式的系统中, 大量的services被发布, 运行期诸多的service相互依赖, 而又不停的升级, 上线, 下线, 为了对它们的优雅的管理, Apache的Curator Service Discovery提供了如下机制:
- service的注册
- 定位给定service的一个可用实例
- service的变更通知
几个概念
ServiceInstance
一个service实例.由name, id, address, port/ssl port, payload(可选)构成, 在Zookeeper中的数据组织结构如下:
base path
|_______ service A name
|__________ instance 1 id --> (serialized ServiceInstance)
|__________ instance 2 id --> (serialized ServiceInstance)
|__________ ...
|_______ service B name
|__________ instance 1 id --> (serialized ServiceInstance)
|__________ instance 2 id --> (serialized ServiceInstance)
|__________ ...
|_______ ...
定义一个实例:
ServiceInstance<InstanceDetails> service = ServiceInstance.<InstanceDetails>builder()
.name(serviceName)
.address(getInnerHostIp())
.port(port)
.id(id)
.serviceType(ServiceType.DYNAMIC)
.payload(new InstanceDetails(id)).build();
ServiceProvider
它封装和提供了依据策略来发现service. 所谓的策略(strategy), 就是从给定service的可用instance中怎么选出一个来的策略. 这些策略有:
- random
- round robin
- sticky
ServiceDiscovery
它用来分配ServiceProvider; 基本上是我们打交道最多的类之一, 几乎所有对instance的操作都是通过它来实现. 参考如下代码.
ServiceDiscovery<String> discovery = ServiceDiscoveryBuilder.builder(String.class).basePath("/test").client(client).basePath(basePath).build();
关于builder()和payload
如上builder()的参数定义了payloadClass, 也就是上面数据结构图里的(serialized ServiceInstance)中的内容.
我们也可以自定义一个复杂的class用来承载更多的信息; 比如 MoreDetails.class, 不过需要告诉系统, 怎么才能把我们自定义的类"变成"Zookeeper里的payload字符串, 方法就是提供serializer:
JsonInstanceSerializer<MoreDetails> serializer = new JsonInstanceSerializer<MoreDetails>(MoreDetails.class);
ServiceDiscovery<String> discovery = ServiceDiscoveryBuilder.builder(String.class).basePath("/test").client(client).basePath(basePath).serializer(serializer).build();
如上是通过json的序列化来完成payload的, 如果有进一步的需求, 比如class到json的自定义映射, 用简单的jackson的标注就可以实现.
实操
//curator client
CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
closeables.add(client);
client.start();
ServiceInstance<String> instance = ServiceInstance.<String>builder().payload("thing").name("test").port(10064).build();
ServiceDiscovery<String> discovery = ServiceDiscoveryBuilder.builder(String.class).basePath("/test").client(client).thisInstance(instance).build();
closeables.add(discovery);
discovery.start();
Assert.assertEquals(discovery.queryForNames(), Collections.singletonList("test"));
CRUD:
serviceDiscovery.start();
serviceDiscovery.registerService(service);
serviceDiscovery.unregisterService(service);
serviceDiscovery.updateService(service);
serviceDiscovery.queryForInstances(serviceName);