当前位置: 首页 > news >正文

ZooKeeper注册中心实现

具体步骤

  1. 安装ZooKeeper(启动端口占用,2181:客户端,8080:管理端)
  2. 引入客户端依赖
  3. 实现注册中心接口
  4. SPI补充ZooKeeper注册中心

引入依赖

<!-- zookeeper -->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-x-discovery</artifactId><version>5.6.0</version>
</dependency>

ZooKeeper注册中心实现

/*** zookeeper 注册中心*/
public class ZooKeeperRegistry implements Registry {private static final Logger logger = LoggerFactory.getLogger(ZooKeeperRegistry.class);private CuratorFramework client;private ServiceDiscovery<ServiceMetaInfo> serviceDiscovery;/*** 本机注册的节点 key 集合(用于维护续期)*/private final Set<String> localRegisterNodeKeySet = new HashSet<>();/*** 注册中心服务缓存*/private final RegistryServiceMultiCache registryServiceMultiCache = new RegistryServiceMultiCache();/*** 正在监听的 key 集合*/private final Set<String> watchingKeySet = new ConcurrentHashSet<>();/*** 根节点*/private static final String ZK_ROOT_PATH = "/rpc/zk";@Overridepublic void init(RegistryConfig registryConfig) {// 构建 client 实例client = CuratorFrameworkFactory.builder().connectString(registryConfig.getAddress()).retryPolicy(new ExponentialBackoffRetry(Math.toIntExact(registryConfig.getTimeout()), 3)).build();// 构建 serviceDiscovery 实例serviceDiscovery = ServiceDiscoveryBuilder.builder(ServiceMetaInfo.class).client(client).basePath(ZK_ROOT_PATH).serializer(new JsonInstanceSerializer<>(ServiceMetaInfo.class)).build();try {// 启动 client 和 serviceDiscoveryclient.start();serviceDiscovery.start();} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic void register(ServiceMetaInfo serviceMetaInfo) throws Exception {// 注册到 zk 里serviceDiscovery.registerService(buildServiceInstance(serviceMetaInfo));// 添加节点信息到本地缓存String registerKey = ZK_ROOT_PATH + "/" + serviceMetaInfo.getServiceNodeKey();localRegisterNodeKeySet.add(registerKey);}@Overridepublic void unRegister(ServiceMetaInfo serviceMetaInfo) {try {serviceDiscovery.unregisterService(buildServiceInstance(serviceMetaInfo));} catch (Exception e) {throw new RuntimeException(e);}// 从本地缓存移除String registerKey = ZK_ROOT_PATH + "/" + serviceMetaInfo.getServiceNodeKey();localRegisterNodeKeySet.remove(registerKey);}@Overridepublic List<ServiceMetaInfo> serviceDiscovery(String serviceKey) {// 优先从缓存获取服务List<ServiceMetaInfo> cachedServiceMetaInfoList = registryServiceMultiCache.readCache(serviceKey);if (cachedServiceMetaInfoList != null) {return cachedServiceMetaInfoList;}try {// 查询服务信息Collection<ServiceInstance<ServiceMetaInfo>> serviceInstanceList = serviceDiscovery.queryForInstances(serviceKey);// 解析服务信息List<ServiceMetaInfo> serviceMetaInfoList = serviceInstanceList.stream().map(ServiceInstance::getPayload).collect(Collectors.toList());// 写入服务缓存registryServiceMultiCache.writeCache(serviceKey, serviceMetaInfoList);return serviceMetaInfoList;} catch (Exception e) {throw new RuntimeException("获取服务列表失败", e);}}@Overridepublic void heartBeat() {// 不需要心跳机制,建立了临时节点,如果服务器故障,则临时节点直接丢失}/*** 监听(消费端)** @param serviceNodeKey 服务节点 key*/@Overridepublic void watch(String serviceNodeKey) {String watchKey = ZK_ROOT_PATH + "/" + serviceNodeKey;boolean newWatch = watchingKeySet.add(watchKey);if (newWatch) {CuratorCache curatorCache = CuratorCache.build(client, watchKey);curatorCache.start();curatorCache.listenable().addListener(CuratorCacheListener.builder().forDeletes(childData -> registryServiceMultiCache.clearCache(serviceNodeKey)).forChanges(((oldNode, node) -> registryServiceMultiCache.clearCache(serviceNodeKey))).build());}}@Overridepublic void destroy() {logger.info("zookeeper注册中心下线...");// 下线节点(这一步可以不做,因为都是临时节点,服务下线,节点就被删掉)for (String key : localRegisterNodeKeySet) {try {client.delete().guaranteed().forPath(key);} catch (Exception e) {throw new RuntimeException(key + "节点下线失败");}}// 释放资源if (client != null) {client.close();}}private ServiceInstance<ServiceMetaInfo> buildServiceInstance(ServiceMetaInfo serviceMetaInfo) {String serviceAddress = serviceMetaInfo.getServiceHost() + ":" + serviceMetaInfo.getServicePort();try {return ServiceInstance.<ServiceMetaInfo>builder().id(serviceAddress).name(serviceMetaInfo.getServiceKey()).address(serviceAddress).payload(serviceMetaInfo).build();} catch (Exception e) {throw new RuntimeException(e);}}
}

添加SPI配置

etcd=com.starlink.registry.EtcdRegistry
zookeeper=com.starlink.registry.ZooKeeperRegistry

image-20241229170512331

最后配置文件指定ZooKeeper为注册中心即可使用ZooKeeper注册中心

rpc.registryConfig.registry=zookeeper
rpc.registryConfig.address=localhost:2181

相关文章:

ZooKeeper注册中心实现

具体步骤 安装ZooKeeper&#xff08;启动端口占用&#xff0c;2181&#xff1a;客户端&#xff0c;8080&#xff1a;管理端&#xff09;引入客户端依赖实现注册中心接口SPI补充ZooKeeper注册中心 引入依赖 <!-- zookeeper --> <dependency><groupId>org.a…...

数仓建模:如何进行实体建模?

目录 1 如何进行实体建模? 业务建模 领域建模 逻辑建模 2 实体建模具体步骤 需求分析...

Python编程技术

设计目的 该项目框架Scrapy可以让我们平时所学的技术整合旨在帮助学习者提高Python编程技能并熟悉基本概念&#xff1a; 1. 学习基本概念&#xff1a;介绍Python的基本概念&#xff0c;如变量、数据类型、条件语句、循环等。 2. 掌握基本编程技巧&#xff1a;教授学生如何使…...

「Mac玩转仓颉内测版55」应用篇2 - 使用函数实现更复杂的计算

本篇教程基于仓颉编程语言扩展了计算器功能&#xff0c;支持加减乘除的基础运算&#xff0c;以及幂运算和开平方等高级功能。代码经过简化后&#xff0c;移除了对输入的复杂校验&#xff0c;提升了程序的可维护性和交互效率。 关键词 仓颉编程语言函数封装高级运算 一、功能说…...

map参数详解

const items new Array(15).fill(null).map((_, index) > ({key: index 1,label: nav ${index 1}, })); $.map() 函数用于使用指定函数处理数组中的每个元素(或对象的每个属性)&#xff0c;并将处理结果封装为新的数组返回。 注意&#xff1a;1. 在jQuery 1.6 之前&#…...

OSI 七层模型 | TCP/IP 四层模型

注&#xff1a;本文为 “OSI 七层模型 | TCP/IP 四层模型” 相关文章合辑。 未整理去重。 OSI 参考模型&#xff08;七层模型&#xff09; BeretSEC 于 2020-04-02 15:54:37 发布 OSI 的概念 七层模型&#xff0c;亦称 OSI&#xff08;Open System Interconnection&#xf…...

高转速风扇|无刷暴力风扇方案设计

在当今科技高速发展的时代&#xff0c;电子设备的性能不断提升&#xff0c;散热问题也日益成为关注的焦点。而 13w 高转速暴力风扇方案的出现&#xff0c;为解决各种设备的散热难题提供了强大的技术支持。 一、高转速暴力风扇的重要性 随着电子设备的不断升级&#xff0c;其功率…...

GPU 进阶笔记(三):华为 NPU/GPU 演进

大家读完觉得有意义记得关注和点赞&#xff01;&#xff01;&#xff01; 1 术语 1.1 CPU1.2 GPU1.3 NPU / TPU1.4 小结2 华为 DaVinci 架构&#xff1a;一种方案覆盖所有算力场景 2.1 场景、算力需求和解决方案2.2 Ascend NPU 设计3 路线一&#xff1a;NPU 用在手机芯片&…...

计算机网络 (13)信道复用技术

前言 计算机网络中的信道复用技术是一种提高网络资源利用率的关键技术。它允许在一条物理信道上同时传输多个用户的信号&#xff0c;从而提高了信道的传输效率和带宽利用率。 一、信道复用技术的定义 信道复用&#xff08;Multiplexing&#xff09;就是在一条传输媒体上同时传输…...

数据库约束和查询

一 约束意义 这个后面的字段是什么意思呢? 先前说数据类型是一种约束&#xff0c;约束我们只能放该类型的数据&#xff0c;还有其它的约束来保证数据的合法性&#xff0c;下面的字段就和约束有关。 编译器的编译就是一个约束&#xff0c;保证我们的代码一定是语法合格的。我们…...

网工日记:FTP两种工作模式的区别

FTP 的主动模式和被动模式在连接建立的发起方、数据传输端口以及对网络环境的适应性等方面存在明显区别&#xff1a; 1. 连接发起方 主动模式&#xff1a;数据连接由服务器主动发起。在控制连接建立后&#xff0c;客户端通过 PORT 命令告知服务器自己用于接收数据的临时端口号…...

NLP模型工程化部署

文章目录 一、理论-微服务、测试与GPU1&#xff09;微服务架构2&#xff09;代码测试3&#xff09;GPU使用 二、实践-封装微服务&#xff0c;编写测试用例和脚本&#xff0c;并观察GPU1&#xff09;微服务封装(RestFul和RPC)2&#xff09;测试编写(unit_test\api_test\load_tes…...

分布式版本管理工具——git 中忽略文件的版本跟踪(初级方法及高级方法)

git工具忽略指定文件的版本跟踪 一、简单方式实现二、复杂方式实现&#xff08;模式匹配&#xff09;1. 相关规则2. 应用案例a) 忽略所有内容b) 忽略所有目录&#xff08;不忽略当前目录的具体文件&#xff09;c)忽略指定目录下的所有文件&#xff0c;但排除某文件d&#xff09…...

【LangChain】Chapter4 - Question and Answer Over Documents

说在前面 文档问答&#xff0c;是常见的一类LLM应用&#xff0c;给定一段可能是从 PDF文件、网页或某公司内部文档库中提取的文本&#xff0c;使用LLM回答关于这些文档内容的问题。这样的应用非常的强大&#xff0c;它可以将LLM与完全没被训练的数据相结合&#xff0c;可以灵活…...

TCP/IP 协议演进中的瓶颈,权衡和突破

所有(去掉 “几乎” 修饰)问题都来自于生长速度的不一致&#xff0c;换句话说&#xff0c;膨胀不是均匀的&#xff0c;从而产生瓶颈甚至触碰极限&#xff0c;TCP/IP 从协议到实现面临的多方问题与动物体型不能无限大&#xff0c;摩天大楼不能无限高本质上一样。 如今被高性能网…...

软件测试面试八股文,查漏补缺(附文档)

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;准备面试了&#xff0c;又不知道从何下手&#xff01;为了帮大家节约时间&#xff0c;特意准备了一份面试相关的资料&#xff0c;内容非常的全面&#xff0c;真的可以好好补一补&#xff0c;希望大家在都能拿到理想的…...

IDEA工具使用介绍、IDEA常用设置以及如何集成Git版本控制工具

文章目录 一、IDEA二、建立第一个 Java 程序三、IDEA 常用设置四、IDEA 集成版本控制工具&#xff08;Git、GitHub&#xff09;4.1 IDEA 拉 GitHub/Git 项目4.2 IDEA 上传 项目到 Git4.3 更新提交命令 一、IDEA 1、什么是IDEA&#xff1f; IDEA&#xff0c;全称为 IntelliJ ID…...

YOLOv10-1.1部分代码阅读笔记-transformer.py

transformer.py ultralytics\nn\modules\transformer.py 目录 transformer.py 1.所需的库和模块 2.class TransformerEncoderLayer(nn.Module): 3.class AIFI(TransformerEncoderLayer): 4.class TransformerLayer(nn.Module): 5.class TransformerBlock(nn.Module)…...

机器人革新!ModbusTCP转CCLINKIE网关揭秘

在当今这个科技日新月异的时代&#xff0c;机器人技术正以前所未有的速度发展着&#xff0c;它们在工业制造、医疗服务、家庭娱乐等多个领域扮演着越来越重要的角色。而随着机器人应用的普及和多样化&#xff0c;如何实现不同设备之间的高效通信成为了一个亟待解决的问题。开疆…...

JWT包中的源码分析【Golang】

前言 最近在学web编程的途中&#xff0c;经过学长提醒&#xff0c;在进行登陆&#xff08;Login&#xff09;操作之后&#xff0c;识别是否登陆的标识应该要放入authorization中&#xff0c;正好最近也在学鉴权&#xff0c;就顺便来看看源码了。 正文 1. 代码示例 在进行分…...

别再只传明文了!SpringBoot若依框架接口Base64加解密避坑指南

若依框架接口安全升级&#xff1a;Base64编码传输的实战陷阱与解决方案 在前后端分离架构中&#xff0c;数据安全传输一直是开发者关注的焦点。最近接手一个金融类项目改造&#xff0c;客户明确要求所有接口数据必须经过编码处理。当我信心满满地准备用Base64方案快速实现时&am…...

为什么鸿蒙多端游戏是未来趋势?

网罗开发&#xff08;小红书、快手、视频号同名&#xff09;大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等方…...

飞跨电容三电平拓扑的实战解析:从数学原理到SiC MOSFET的高频设计

1. 飞跨电容三电平拓扑的数学起源 飞跨电容三电平&#xff08;FCML&#xff09;拓扑的命名并非随意&#xff0c;它实际上植根于18世纪的数学拓扑学。数学拓扑学研究的是几何图形在连续变形下保持不变的性质&#xff0c;这个概念最早由欧拉在1736年研究柯尼斯堡七桥问题时提出。…...

HsMod:革新性炉石传说增强工具,全方位提升游戏体验

HsMod&#xff1a;革新性炉石传说增强工具&#xff0c;全方位提升游戏体验 【免费下载链接】HsMod Hearthstone Modification Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod 一、你是否也面临这些游戏痛点&#xff1f; 当你兴致勃勃地开启…...

小团队福音:用两台服务器搞定Redis高可用(Keepalived+互为主从配置)

小团队福音&#xff1a;用两台服务器构建轻量级Redis高可用架构 在初创公司和小型技术团队中&#xff0c;服务器资源往往捉襟见肘。当业务需要Redis作为缓存或数据库时&#xff0c;传统的高可用方案如哨兵模式需要至少三台服务器&#xff0c;这对资源有限的团队来说可能过于奢侈…...

低代码不是妥协,而是进化:.NET 9 AOT+Hot Reload双模引擎深度解析,上线周期压缩至72小时以内

第一章&#xff1a;低代码不是妥协&#xff0c;而是进化&#xff1a;.NET 9 AOTHot Reload双模引擎深度解析&#xff0c;上线周期压缩至72小时以内在传统认知中&#xff0c;“低代码”常被误读为牺牲可控性与性能的权宜之计。而.NET 9通过原生AOT编译与Hot Reload能力的深度融合…...

【权威实测|2026.03.15 CPython核心团队签发】:Python原生AOT插件下载失败率骤降92%,但90%开发者仍卡在第2步安装验证

第一章&#xff1a;Python原生AOT编译方案2026插件下载与安装概览Python原生AOT&#xff08;Ahead-of-Time&#xff09;编译方案2026是CPython官方实验性路线图中的关键演进&#xff0c;旨在为Python代码提供零运行时依赖的二进制输出能力。该方案不依赖PyInstaller或Nuitka等第…...

二叉树层序遍历与高度计算详解

一、先解答上次的思考题Day12 已经给出练习答案&#xff0c;这里不再重复&#xff0c;我们直接进入层序遍历。二、今天学习目标理解层序遍历&#xff08;按一层一层打印&#xff09;用队列实现层序遍历&#xff08;BFS 思想&#xff09;递归 迭代两种方式求二叉树高度完整可运…...

从‘炼丹’到‘产线’:手把手教你用AutoDockTools和Python脚本搭建可复现的批量分子对接流程

从‘炼丹’到‘产线’&#xff1a;手把手教你用AutoDockTools和Python脚本搭建可复现的批量分子对接流程 在药物发现和生物分子相互作用研究中&#xff0c;分子对接技术已成为虚拟筛选和先导化合物优化不可或缺的工具。然而&#xff0c;当面对数十甚至上百个小分子配体时&#…...

Pixel Language Portal应用场景深度挖掘:支持波斯语/梵文的学术文献跨维翻译工作流

Pixel Language Portal应用场景深度挖掘&#xff1a;支持波斯语/梵文的学术文献跨维翻译工作流 1. 学术翻译的新范式 在全球化知识共享的背景下&#xff0c;学术研究者经常面临古老语言文献的翻译难题。传统翻译工具对波斯语、梵文等特殊语种支持有限&#xff0c;更难以处理学…...