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

RPC框架引入zookeeper服务注册与服务发现

Zookeeper概念及其作用

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是大数据生态中的重要组件。它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

它是一个为分布式应用提供一致性协调服务的中间件
zookeeper入门参考链接:https://www.cnblogs.com/xinyonghu/p/11031729.html

在分布式系统中,zookeeper提供了非常丰富的应用,本文只是剖析其中一小部分,但也是非常重要的一个部分,即服务注册和服务发现。
在RPC框架中,如果没有服务注册和服务发现,那么这个RPC框架几乎变得不实用,浅显的思路是在RPCConsumer(服务调用端)维护一个服务的列表,这个列表包含了所有分布式节点服务的ip和端口,但考虑这么一种情况,如果其中某个节点由于某种原因down掉了或者将这个节点的服务删除了,但是RPCConsumer本地还维护的列表中还存在这个服务结点,并且还尝试请求这个服务,那么显然会调用出错。
在这里插入图片描述

类似这种肯定需要动态的维护每个分布式服务节点的状态,在该节点down掉或者被撤销时应及时删除这个服务,避免RPC调用端继续请求不存在的服务。这就是zookeeper服务注册和服务发现所做的事。

在这里插入图片描述
Zookeeper组织数据的格式类似于一个文件系统,每个znode结点都可以是一个分布式服务结点,一般组织的结构是XXXXService/login、 XXXXService/registe,即service_name/method_name,znode结点的数据就是该服务所在节点的ip和port
在这里插入图片描述

Zookeeper服务注册和发现的流程:

step1:Rpc服务端先通过zkClient向zkServer端注册服务,也即创建XXXXService/login、 XXXXService/registe节点,并填充相应的数据。
step2:Rpc调用端再调用某个服务之前,通过zkClient向ZkServer查询这个服务节点是否存在,如果存在则返回这个服务节点的ip和port。然后进行远程rpc调用,否则返回错误终止调用过程。
step3:这一步其实zookeeper已经帮我们做了,step1中注册服务的过程中,zkServer会与这个节点建立一个session,并且zkServer以1/3 * timeout 的时间定期为每个与之简历的节点发送心跳包,如果得不到回应那么zkServer会认为这个节点已经不存在了,会动态的把这个节点上的所有服务都进行删除。

RPC框架引入zookeeper

1、封装zkclient(用于与zkServer通信的句柄、例如创建结点和删除结点、以及一些心跳回调操作)

#pragma once#include <semaphore.h>
#include <zookeeper/zookeeper.h>
#include <string>class ZkClient
{
public: ZkClient();~ZkClient();// zkClient启动连接zkservervoid Start();// 在zkserver上根据指定的path创建Znode节点void Create(const char *path, const char* data, int datalen, int state=0);// 根据参数指定的znode节点路径,获取znode节点的值std::string GetData(const char* path);private:// zk客户端句柄zhandle_t *m_zhandle;
};// .cc
#include "zookeeperutil.h"
#include "rpcapplication.h"
#include  <iostream>//全局的watcher观察器     zkserver给zkclient的通知回调
void global_watcher(zhandle_t *zh, int type, int state, const char* path, void *watcherCtx)
{if(type == ZOO_SESSION_EVENT)    //回调的消息类型是和会话相关的消息类型{if(state == ZOO_CONNECTED_STATE)  //zkserver和zkclient连接成功{sem_t *sem = (sem_t*) zoo_get_context(zh);sem_post(sem);}}
}ZkClient::ZkClient():m_zhandle(nullptr)
{}
ZkClient::~ZkClient()
{if(m_zhandle != nullptr){zookeeper_close(m_zhandle);   //关闭句柄, 释放资源}
}
// zkClient启动连接zkserver
void ZkClient::Start()
{std::string host = RpcApplication::GetInstance().GetConfig().Load("zookeeperip");std::string port = RpcApplication::GetInstance().GetConfig().Load("zookeeperport");std::string connstr = host + ":" + port;/*zookeeper_mt:多线程版本zookeeper的API客户端程序提供了三个线程APT调用线程网络I/O线程  pthread_create (使用的poll-IO多路复用)watcher回调线程 pthread_create*/m_zhandle = zookeeper_init(connstr.c_str(), global_watcher, 30000, nullptr, nullptr, 0);if(nullptr == m_zhandle){std::cout << "zookeeper_init error !" << std::endl;exit(EXIT_FAILURE);}sem_t sem;sem_init(&sem, 0, 0);zoo_set_context(m_zhandle, &sem);sem_wait(&sem);std::cout << "zookeeper_init success !" << std::endl;
}// 在zkserver上根据指定的path创建Znode节点
void ZkClient::Create(const char *path, const char* data, int datalen, int state)
{char path_buffer[128];int bufferlen = sizeof(path_buffer);int flag;//先判断path表示的znode节点是否存在, 如果存在, 就不能重复创建了flag = zoo_exists(m_zhandle, path, 0, nullptr);if(ZNONODE == flag)   //表示path的znode节点不存在{// 创建指定path的znode节点flag = zoo_create(m_zhandle, path, data, datalen, &ZOO_OPEN_ACL_UNSAFE, state, path_buffer, bufferlen);if(flag == ZOK){std::cout << "znode create success .... path:" << path << std::endl;}else{std::cout << "flag : " << flag <<std::endl;std::cout << "znode create error...path: " << path << std::endl;exit(EXIT_FAILURE);}}
}// 根据参数指定的znode节点路径,获取znode节点的值
std::string ZkClient::GetData(const char* path)
{char buffer[64];int bufferlen = sizeof(buffer);int flag = zoo_get(m_zhandle, path, 0, buffer, &bufferlen, nullptr);if(flag != ZOK){std::cout << "get znode error ...... path" << path << std::endl;return "";}else{return buffer;}
}

2、在RPCProvider端进行服务注册

//把当前rpc节点上要发布的服务全部注册到zk上面, 让rpc client可以从zk上发现服务// session timeout 30s          zkclient 的网络I/O线程 会定时以1/3 * timeout 时间去给zkserver发送ping心跳包ZkClient zkCli;zkCli.Start();//service name为永久性节点      method name 为临时性节点for(auto& sp : m_serviceMap){// /service_name   ---> /UserServiceRPcstd::string service_path = "/" + sp.first;zkCli.Create(service_path.c_str(), nullptr, 0);for(auto &mp : sp.second.m_methodMap){// /service_name/method_name /UserServiceRPc/Login 存储当前这个rpc服务节点主机的ip和portstd::string method_path = service_path + "/" + mp.first;char method_path_data[128] = {0};sprintf(method_path_data, "%s:%d", ip.c_str(), port);//ZOO_EPHEMERAL 表示znode是一个临时性节点zkCli.Create(method_path.c_str(), method_path_data, strlen(method_path_data), ZOO_EPHEMERAL);}}

3、RPCConsumer端进行服务发现

//rpc调用方想调用service_name的method_name的服务, 需要查询zk上该服务所在的host信息ZkClient zkCli;zkCli.Start();// /UserServiceRpc/Loginstd::string method_path = "/" + service_name + "/" + method_name;// 127.0.0.1:8000std::string host_data = zkCli.GetData(method_path.c_str());if(host_data == ""){controller->SetFailed(method_path + "is not exist!");return;}int idx = host_data.find(":");if(idx == -1){controller->SetFailed(method_path + "address is invalid!");return;}std::string ip = host_data.substr(0, idx);uint16_t port = atoi(host_data.substr(idx + 1, host_data.size() - idx).c_str());

至此基本上完整RPC应该具备的核心东西都有了。

相关文章:

RPC框架引入zookeeper服务注册与服务发现

Zookeeper概念及其作用 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是大数据生态中的重要组件。它是集群的管理者&#xff0c;监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理…...

MySQL用通配符过滤数据

简单的不使用通配符过滤数据的方式使用的值都是已知的&#xff0c;但是当搜索产品名中包含ashui的所有产品时&#xff0c;用简单的比较操作符肯定不行&#xff0c;必须使用通配符。利用通配符可以创建比较特定数据的搜索模式。 通配符&#xff1a;用来匹配值的一部分的特殊字符…...

低通、高通、带通、阻通滤波器

目录 低通、高通、带通、阻通滤波器 低通、高通、带通、带阻滤波器的区别 通俗理解&#xff1a; 1、低通滤波器 2、高通滤波器 3、带通滤波器 4、带阻滤波器 5、全通滤波器 低通、高通、带通、阻通滤波器 低通、高通、带通、带阻滤波器的区别 低通滤波器&#xff1a;只…...

IDEA SpringBoot Maven profiles 配置

IDEA SpringBoot Maven profiles 配置 IDEA版本&#xff1a; IntelliJ IDEA 2022.2.3 注意&#xff1a;切换环境之后务必点击一下刷新&#xff0c;推荐点击耗时更短。 application.yaml spring:profiles:active: env多环境文件名&#xff1a; application-dev.yaml、 applicat…...

微信小程序 背景图片如何占满整个屏幕

1. 在页面的wxss文件中&#xff0c;设置背景图片的样式&#xff1a; page{background-image: url(图片路径);background-size: 100% 100%;background-repeat: no-repeat; } 2. 在页面的json文件中&#xff0c;设置背景图片的样式&#xff1a; {"backgroundTextStyle&qu…...

邪恶版ChatGPT来了!

「邪恶版」ChatGPT 出现&#xff1a;每月 60 欧元&#xff0c;毫无道德限制&#xff0c;专为“网络罪犯”而生。 WormGPT 并不是一个人工智能聊天机器人&#xff0c;它的开发目的不是为了有趣地提供无脊椎动物的人工智能帮助&#xff0c;就像专注于猫科动物的CatGPT一样。相反&…...

一、Postfix[安装与配置、smtp认证、Python发送邮件以及防垃圾邮件方法、使用腾讯云邮件服务]

Debian 11 一、安装 apt install postfix 二、配置 1.dns配置 解释&#xff1a;搭建真实的邮件服务器需要在DNS提供商那里配置下面的dns 配置A记录mail.www.com-1.x.x.x配置MX记录www.com-mail.www.com 解释&#xff1a;按照上面的配置通常邮件格式就是adminwww.com其通过…...

React哲学——官方示例

在本篇技术博客中&#xff0c;我们将介绍React官方示例&#xff1a;React哲学。我们将深入探讨这个示例中使用的组件化、状态管理和数据流等核心概念。让我们一起开始吧&#xff01; 项目概览 React是一个流行的JavaScript库&#xff0c;用于构建用户界面。React的设计理念是…...

设计模式之开闭原则

什么是开闭原则? 开放封闭原则称为OCP原则&#xff08;Open Closed Principle&#xff09;是所有面向对象原则的核心。 “开闭原则”是面向对象编程中最基础和最重要的设计原则之一。 软件设计本身所追求的目标就是封装变化、降低耦合&#xff0c;而开放封闭原则正是对这一…...

Linux中的file命令:查看文件类型

2023年8月1日&#xff0c;周二上午 目录 简要说明使用方法MIME类型举例说明 简要说明 在Linux中&#xff0c;file命令用于识别文件类型。 file命令可以识别各种类型的文件&#xff0c;包括普通文件、目录、符号链接、设备文件、压缩文件、二进制可执行文件等。 它是一个非常…...

使用WiFi测量仪进行机器人定位的粒子过滤器研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

【vue】vue 里面使用 v-html 插入的文本带有换行符‘\n‘不换行

最近开发vue2 项目 &#xff0c;接口返回的是类似于这样的数据&#xff1a;我是第一行的哦\n我是第二行的哦 我是直接这样渲染的&#xff0c; //html <p v-htmltext></p>//渲染值 this.text "我是第一行的哦\n我是第二行的哦"但结果却是不如意&#x…...

Java失效算法与应用(FIFO、LRU、LFU)

文章目录 一、什么是失效算法二、先来先淘汰&#xff08;FIFO&#xff09;1、FIFO概述2、Java实现FIFO3、FIFO特点 三、最久未用淘汰&#xff08;LRU&#xff09;1、LRU概述2、Java实现LRU 四、最近最少使用&#xff08;LFU&#xff09;1、LFU概述2、Java实现LFU 五、应用案例 …...

Go语音介绍

Go语言介绍 Go 即Golang&#xff0c;是Google公司2009年11月正式对外公开的一门编程语言。 Go是静态强类型语言&#xff0c;是区别于解析型语言的编译型语言。 解析型语言——源代码是先翻译为中间代码&#xff0c;然后由解析器对代码进行解释执行。 编译型语言——源代码编…...

Vue2与Vue3响应式原理

Vue2的响应式 Vue3的响应式...

flask中写一个基础的sqlHelper类

写一个SQLHelper类&#xff1a; from flask_sqlalchemy import SQLAlchemydb SQLAlchemy()class SQLHelper:staticmethoddef add(record):db.session.add(record)return SQLHelper.session_commit()staticmethoddef add_all(records):db.session.add_all(records)return SQLH…...

opencv的Mask操作,选择图片中感兴趣的区域

最近做目标检测任务的时候&#xff0c;需要对固定区域的内容进行检测&#xff0c;要用到opencv的mask操作&#xff0c;选择图片固定的区域 代码 import cv2 import numpy as npimg cv2.imread(data/images/smoking.png)# 弹出一个框 让你选择ROI | x,y是左上角的坐标 x,y,w,…...

一次有趣的Webshell分析经历

一次有趣的Webshell分析经历 1.拉取源代码2.解密后门代码3.分析webshell逻辑4.分析404的原因5.附&#xff1a;格式化后的php代码 1.拉取源代码 在对某目标做敏感目录收集时发现对方网站备份源代码在根目录下的 backup.tar.gz&#xff0c;遂下载&#xff0c;先使用D盾分析有没有…...

【NLP概念源和流】 05-引进LSTM网络(第 5/20 部分)

一、说明 在上一篇博客中,我们讨论了原版RNN架构,也讨论了它的局限性。梯度消失是一个非常重要的缺点,它限制了RNN对较短序列的建模。香草 RNN 在相关输入事件和目标信号之间存在超过 5-10 个离散时间步长的时间滞时无法学习。这基本上限制了香草RNN在许多实际问题上的应用,…...

Vue没有node_modules怎么办

npm install 一下 然后再npm run serve 就可以运行了...

经典算法实现:二分查找、全排列与子集生成

在算法学习中&#xff0c;二分查找、全排列、子集生成是非常基础且重要的内容。本文将结合 C 代码&#xff0c;详细讲解这三种经典算法的实现思路与核心逻辑&#xff0c;帮助大家理解算法的底层原理和代码落地方式。一、二分查找&#xff08;Binary Search&#xff09;二分查找…...

从CPython 3.12到3.14:我们逆向了217个AOT相关PR,提炼出6个决定编译成功率的核心宏定义(含Py_BUILD_CORE_MODULE与Py_LIMITED_API冲突解决方案)

第一章&#xff1a;Python 原生 AOT 编译方案 2026 高级开发技巧Python 社区在 2026 年迎来关键演进&#xff1a;CPython 官方正式集成原生 Ahead-of-Time&#xff08;AOT&#xff09;编译能力&#xff0c;无需依赖第三方运行时或 JIT 层即可生成平台专用的静态可执行文件。该特…...

CDN 无法播放音视频?流媒体回源与 Range 配置修复

流媒体应用现在越来越普及&#xff0c;CDN&#xff08;内容分发网络&#xff09;早已成为音视频流畅播放的核心支撑——靠边缘节点就近分发&#xff0c;既能降低延迟&#xff0c;又能减轻源站压力&#xff0c;让用户不用长时间等待就能看高清内容。但实际运维中&#xff0c;“C…...

如何写 Skill

核心概念 Skill 是一个自包含的模块&#xff0c;用来给 Claude/Cascade 注入特定领域的知识、工作流和工具。本质上就是一个"新手入职指南"&#xff0c;让通用 AI 变成某个领域的专家。 目录结构 skill-name/ ├── SKILL.md # 必须&#xff0c;核心文件 └…...

芯片缺货潮下的应对策略与国产替代方案

1. 芯片缺货潮下的行业现状最近我的一个产品项目中&#xff0c;原本采购价仅5元的ST品牌MCU&#xff08;微控制器&#xff09;价格飙升至70元&#xff0c;涨幅高达14倍。这个案例并非个例&#xff0c;而是当前全球半导体行业供应链危机的缩影。作为从业十余年的硬件工程师&…...

告别‘千人千脑’:用DMMR模型搞定EEG情感识别的跨被试难题(附PyTorch代码)

突破脑电情感识别的个体差异壁垒&#xff1a;DMMR模型实战指南与PyTorch实现 当你在实验室里看着屏幕上跳动的脑电波形时&#xff0c;是否曾为不同受试者数据间的巨大差异而头疼&#xff1f;这种被称为"脑电指纹"的个体特异性&#xff0c;一直是情感识别领域最棘手的…...

Qwen3.5-9B惊艳效果:上传物理实验图→识别仪器→生成操作步骤视频脚本

Qwen3.5-9B惊艳效果&#xff1a;上传物理实验图→识别仪器→生成操作步骤视频脚本 1. 模型能力概览 Qwen3.5-9B是一款拥有90亿参数的开源大语言模型&#xff0c;在多模态理解和逻辑推理方面表现出色。这个模型最令人惊艳的能力在于它能够&#xff1a; 准确识别实验仪器&…...

设备管理系统是什么?如何建立设备管理体系?

在现代企业的运转中&#xff0c;生产设备无疑是核心资产。无论是制造业的数控机床&#xff0c;还是建筑工地的重型机械&#xff0c;甚至是医疗机构的精密仪器&#xff0c;设备的稳定运行直接决定了企业的生产效率、产品质量和成本控制。然而&#xff0c;许多企业在设备管理上仍…...

新手入门服务器:用快马生成你的第一个xshell等效连接程序

作为一个刚接触服务器运维的新手&#xff0c;第一次使用xshell这类工具时&#xff0c;面对各种专业术语和复杂操作确实容易一头雾水。最近我发现用InsCode(快马)平台生成学习项目特别适合入门&#xff0c;今天就分享一下如何通过可运行的代码实例来理解SSH连接的核心概念。 理解…...

VisionPro —— CogImageFileTool图像文件管理实战解析

1. CogImageFileTool核心功能解析 第一次接触CogImageFileTool时&#xff0c;我完全被它强大的图像管理能力震撼到了。这个工具就像工业视觉领域的"智能文件管家"&#xff0c;专门处理图像文件的读写和存储问题。想象一下&#xff0c;你每天要处理上千张生产线上的产…...