zk官方注册中心(mulicast zk nacos redis)
@reference 远程调用 消费者
从zookeeper获取 访问url
注册中心挂了,服务正常访问:
消费者第一次调用将提供方缓存到本地,调用不再访问注册中心
提供者地址改变,注册中心通知消费者
超时机制 重试无法完成服务访问 自动断开链接,默认1000 1s
@service(timeout=1000,retries=2 )提供方,建议配置在这 自己知道自己情况
@reference(time=1000) 消费者,覆盖提供方配置
版本:reference(version="v2.0")
负载均衡:@service(weight=100)
random:权重随机weight=100 正相关
roundRobin权重轮询***
leastActive最少活跃调用数 相同随机 (最少执行时间)
最后一次处理请求花费时长,调用时长最短
consistenHash一致性hash 相同参数请求同一个提供者
集群容错
@reference(cluster="failover") 消费者
失败重试 failover
默认,适用读操作 当前失败重试其他机器 默认重试2次 retries配置
快速失败 failfast
失败即报错 写操作
failsafe
失败安全,忽略异常 返回空结果
failback
失败自动恢复,后天记录失败请求 定时重发
forking
并行调用多个服务器,一个成功即返回
broadcast
广播all提供者,任意一台报错则报错
服务降级 reference
mock=force:return null 调用服务方法时直接返回null ,屏蔽不重要服务不可用时
mock=fail:return null 调用服务方法失败后返回null,不重要服务不稳定时
reference(mock="force:return null")
zk
znode 数据和节点信息
节点类型
persistent持久节点
ephemeral临时节点 -e
persistent_sequential持久化顺序节点 -s
ephemeral_sequential临时顺序节点 -es
命令
create /app1 testcontext
create /app1/p1
get /app1
set /app2 testcontext
delete /app1
ls -s 目录 ,查看详细信息
配置管理
分布式锁
curator java客户端
原生/zkclient 不太好用
CuratorFrameworkFactory.newClient(连接ip:port,ip:port,ip:port,sessionTimeoutMs会话超时时间,connectionTimeoutMs连接超时时间,retyPolicy重试策略)
client.start();
方式二:
CuratorFrameworkFactory.builder()
.connectString("")//连接字符串ip:port
.sessionTimeoutMs()//会话超时
.connectionTimeoutMs()//连接超时
.retryPolicy()//重试策略
.namespace()//根目录
.build();
创建节点:持久 临时-e 持久顺序-s 临时顺序-es
client.create().withMode().forPath(String path,byte[] context);//如果创建节点未指定数据以当前客户端ip作为数据存储
查询节点
//查询节点数据
byte[] data = client.getData().forPath("/path");
//获取子路径
List<String> path = client.getChildren().forPath("/path/p1");//查询子节点
//获取状态
Stat status = new Stat();
client.getData().storingStatIn(status).forPath("");
system.out.println(status);
//修改数据,保证数据一致性
int version = status.getVersion();
client.setData().withVersion(version).forPath("/app1","string".getBytes());
//简单方式set
client.setData().forPath("/app1","string".getBytes());
//删除节点delete
client.delete().forPath();
//删除带有子节点deletingChildrenIfNeeded
client.delete().deletingChildrenIfNeeded().forPath("/app4");
//必须删除成功guaranteed
client.delete().guaranteed().forPath("/app1");
//回调inBackground
client.delete().guaranteed().inBackground(
{
new BackgroundCallback(){
@Override
public void processResult(CuratorFramework client,CuratorEvent event) throws Exception{
}
}
}
).forPath("/app1");
watch事件监听
在指定节点上注册一些watcher 由特定事件触发 将事件通知到感兴趣的客户端上
发布/订阅
zk原生需要自己反复注册watcher进行事件监听 繁琐
nodeCache监听特定节点
NodeCache nodeCache = new NodeCache("/app1");
nodeCache.getListenable().addListener(new NodeCacheListener(){
@Override
public void nodeChanged() throws Exception{
//节点变化了
//获取修改节点后的数据
byte[] data= nodeCache.getCurrentData().getData();
}
});
PathChildrenCache监听ZNode子节点
//创建
PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/app2",true);
//绑定
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener(){
@Override
public void childEvent(CuratorFramework client,PathChildrenCacheEvent event) throws Exception{
//子节点变化了
//监听子节点数据变更 拿到更新后数据
PathChildrenCacheEvent.Type type = event.getType();
if(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
byte[] data = event.getData().getData();
}
}
});
pathChildrenCache.start();
TreeCache监控整个树上所有节 点类似PathChildrenCache和NodeCache组合
TreeCache treeCache = new TreeCache(client,"/app2");
treeCache.getListenable().addListener(new TreeCacheListener(){
@Override
public void childEvent(CuratorFramework client,TreeCacheEvent event) throws Exception{
//节点变了
}
});
集群管理
分布式锁
获取锁 在lock节点下 创建临时顺序节点
获取lock下所有子节点 发现自己创建的子节点序号最小 获得了锁 使用完删除该锁
并非最小 找到比自己小的节点 注册事件监听器 监听删除事件
watcher监听到删除通知,判断是否min 是获取了锁否重复以上步骤
锁方案:
InterProcessSemaphoreMutex 分布式排他锁 (非可重入锁)
InterProcessMutex 分布式可重入 排他锁
InterProcessReadWriteLock 读写锁
InterProcessMultiLock 多个锁作为单个实体管理的容器
InterProcessSemaphoreV2 共享信号量
获取锁 lock.acquire(time,timeUnit);
释放锁 lock.release
集群:
leader选举:
serverid 服务器id 编号越大在选择算法中权重越大
zxid 数据id :服务器中存放最大的数据id 值越大数据越新 选举算法中权重越大
角色
leader 处理事务请求 各服务器调度者(同步数据给各服务器)
follower跟随者 非事务请求 转发事务请求给leader 投票
observer观察者 非事务请求 转发事务请求给leader