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

这篇具有很好参考价值的文章主要介绍了RPC框架引入zookeeper服务注册与服务发现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Zookeeper概念及其作用

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

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

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

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

RPC框架引入zookeeper服务注册与服务发现,分布式,rpc,zookeeper,c++,分布式
Zookeeper组织数据的格式类似于一个文件系统,每个znode结点都可以是一个分布式服务结点,一般组织的结构是XXXXService/login、 XXXXService/registe,即service_name/method_name,znode结点的数据就是该服务所在节点的ip和port
RPC框架引入zookeeper服务注册与服务发现,分布式,rpc,zookeeper,c++,分布式

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启动连接zkserver
    void 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   ---> /UserServiceRPc
                std::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和port
                        std::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/Login
     std::string method_path = "/" + service_name + "/" + method_name;
     // 127.0.0.1:8000
     std::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应该具备的核心东西都有了。文章来源地址https://www.toymoban.com/news/detail-623688.html

到了这里,关于RPC框架引入zookeeper服务注册与服务发现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 分布式服务框架_Zookeeper--管理分布式环境中的数据

    安装和配置详解 本文介绍的 Zookeeper 是以 3.2.2 这个稳定版本为基础,最新的版本可以通过官网   http://hadoop.apache.org/zookeeper/ 来获取, Zookeeper 的安装非常简单,下面将从单机模式和集群模式两个方面介绍 Zookeeper 的安装和配置。 单机模式

    2024年02月12日
    浏览(39)
  • Linux分布式应用 Zabbix监控配置[添加主机 自定义监控内容 邮件报警 自动发现/注册 代理服务器 高可用集群]

    关闭防火墙  服务端和客户端都配置时间同步 服务端和客户端都设置 hosts 解析 设置 zabbix 的下载源,安装 zabbix-agent2 修改 agent2 配置文件 启动 zabbix-agent2 在服务端验证 zabbix-agent2 的连通性 在 Web 页面中添加 agent 主 机 点击左边菜单栏【配置】中的【主机】,点击【创建主机

    2024年02月13日
    浏览(57)
  • 如何保证分布式系统中服务的高可用性:应对 ZooKeeper Leader 节点故障的注册处理策略

    作者:zhaokk 在现代分布式系统中,高可用性是一个至关重要的。分布式系统中的各个组件需要保证在各种异常情况下仍然能够正常工作,确保系统的稳定性和可靠性。ZooKeeper(以下简称为zk)作为一种常用的分布式协调服务,为分布式系统中的各种任务提供了基础支持

    2024年02月11日
    浏览(64)
  • SpringBoot整合Dubbo和Zookeeper分布式服务框架使用的入门项目实例

    Dubbo是一个 分布式服务框架 ,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求。其本质上是个远程服务调用

    2024年01月21日
    浏览(49)
  • .NET CORE开源 DDD微服务 支持 多租户 单点登录 多级缓存、自动任务、分布式、日志、授权和鉴权 、网关 、注册与发现 系统架构 docker部署

    源代码地址https://github.com/junkai-li/NetCoreKevin 基于NET6搭建跨平台DDD思想WebApi架构、IDS4单点登录、多缓存、自动任务、分布式、多租户、日志、授权和鉴权、CAP、SignalR、 docker部署  如需简约项目可直接去除项目引用 解耦设计都可以单独引用 架构默认全部引用并启动 项目启动时

    2023年04月24日
    浏览(47)
  • 【分布式技术】注册中心zookeeper

    目录 一、ZooKeeper是什么 二、ZooKeeper的工作机制 三、ZooKeeper特点 四、ZooKeeper数据结构 五、ZooKeeper应用场景 ●统一命名服务 ●统一配置管理 ●统一集群管理 ●服务器动态上下线 ●软负载均衡 六、ZooKeeper的选举机制 七、实操部署ZooKeeper集群 步骤一:先部署java环境 步骤二:

    2024年01月23日
    浏览(41)
  • RPC分布式通信框架

    在实际开发中单机服务器存在诸多问题: 1.受限于硬件资源无法提高并发量 2.任意模块的修改都将导致整个项目代码重新编译部署 3.在系统中,有些模块属于CPU密集型,有些属于I/O密集型,各模块对于硬件资源的需求不一样 什么是分布式?分布式是否可以解决以上问题? 分

    2024年04月28日
    浏览(42)
  • [自动化分布式] Zabbix自动发现与自动注册

    abbix 自动发现(对于 agent2 是被动模式) zabbix server 主动的去发现所有的客户端,然后将客户端的信息登记在服务端上。 缺点是如果定义的网段中的主机数量多,zabbix server 登记耗时较久,且压力会较大  添加zabbix 客户端 主机 (192.168.17.31) 服务端和客户端都配置时间同步

    2024年01月21日
    浏览(40)
  • 分布式 RPC 框架HSF

    HSF (High-speed Service Framework),高速服务框架,是在阿里巴巴内部广泛使用的分布式 RPC 服务框架。 HSF 作为阿里巴巴的基础中间件,联通不同的业务系统,解耦系统间的实现依赖。HSF 从分布式应用的层面,统一了服务的发布/调用方式,从而帮助用户可以方便、快速的开发分布式

    2024年02月16日
    浏览(43)
  • 分布式RPC框架Dubbo详解

    目录   1.架构演进 1.1 单体架构 1.2  垂直架构 1.3 分布式架构 1.4 SOA架构 1.5 微服务架构 2.RPC框架 2.1 RPC基本概念介绍 2.1.1 RPC协议 2.1.2 RPC框架 2.1.3 RPC与HTTP、TCP/ UDP、Socket的区别 2.1.4 RPC的运行流程  2.1.5 为什么需要RPC 2.2 Dubbo  2.2.1 Dubbo 概述 2.2.2 Dubbo实战   架构演进如下图: 这

    2024年02月07日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包