前言
今天基于zk实现了一个简易的服务注册中心,记录一下实现思路。
应用场景
首先,前几天搭建了基于Netty实现的远程服务调用系统(都是简易的,重在思想)。但是存在个问题:A服务调用B服务时(Netty Client 访问 Netty Server),IP Address 和 Port 参数都是写死的,实际生产中肯定不能这样。
需要满足:
- IP动态可配置,且要统一配置。可以通过第三方组件统一管理。
- 每个服务都要高可用。即有多个服务地址,可以进行负载均衡,防止单点故障。
- 服务之间可以动态感知服务地址的上下线。即A服务中的某台服务器宕机后,B服务调用A服务时,宕机服务器地址不再出现在负载均衡的选项中。
技术选型
Zookeeper这个分布式协调组件就派上用场了,或者说这是zk主要的应用场景之一。其实听名字也可以猜测到:动物园管理员?。
zk的主要应用场景有:服务注册中心、master选举、分布式锁、分布式事务一致性等。
实现思路
服务注册端
- 使用zk的持久节点来存储serviceName。持久节点只有用户手动删除时才会消失。
- 使用zk的临时节点来存储serviceAddress。临时节点的生命周期与会话相同,会话结束(服务地址宕机),临时节点自动删除。这就实现了服务地址的动态感知。
服务调用端
- 向调用的服务节点注册监听(PathChildrenCacheListener)。即该节点的子节点放生变更时,更新该节点在调用端缓存的地址信息。
代码
pom.xml
zookeeper客户端框架主要有zkclient和curator。这里我们使用curator,∵curator提供了更多场景的实现。
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.6.0</version>
</dependency>
项目结构
红框内为此次代码添加部分。
registerCenter包为服务注册,discovery包为服务发现。
服务注册
没什么可说的,服务名称设为永久节点,服务地址设为临时节点。
public interface IRegistryCenter {
/**
* 实现服务的管理
* @param serviceName 服务注册名称
* @param serviceAddress 服务注册地址
*/
void registry(String serviceName, String serviceAddress);
}
public class RegistryCenterWithZk implements IRegistryCenter{
CuratorFramework curatorFramework =null;
{
//初始化zookeeper的连接, 会话超时时间是5s,衰减重试
//namespace 命名空间,作用:隔离
curatorFramework = CuratorFrameworkFactory.builder().
connectString(ZkConfig.CONNECTION_STR).sessionTimeoutMs(5000).
retryPolicy(new ExponentialBackoffRetry(1000, 3)).
namespace("registry")
.build();
curatorFramework.start()