即时通讯项目--(3)etcd二次封装

二次封装:封装etcd-client-api,实现两种类型的客户端

1.服务注册客户端:向服务器新增服务信息数据,并进行保活

2.服务发现客户端:从服务器查找服务信息数据,并进行改变事件监控

封装的时候,我们尽量减少模块之间的耦合度,本质上etcd是一个键值存储系统,并不是专门用于作为注册中心进行服务注册和发现的。

封装思想:

1.封装服务注册客户端类

提供一个接口:向服务器新增数据并进行保活

参数:注册中心地址(etcd服务器地址),

新增的服务信息(服务名-主机地址键值对)

2.封装服务发现客户端类

提供两个设置回调函数的接口:服务上线事件接口(数据新增),服务下线事件接口(数据删除)

提供一个设置根目录的接口:用于获取指定目录下的数据以及监控目录下数据的改变

复制代码
#pragma once
#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Watcher.hpp>
#include <etcd/Value.hpp>
#include <functional>
#include "logger.hpp"

namespace im{

//服务注册客户端类
class Registry{
public:
    using ptr = std::shared_ptr<Registry>;

    Registry(const std::string& host): 
        _client(std::make_shared<etcd::Client>(host)),  // 1. 创建etcd客户端
        _keep_alive(_client->leasekeepalive(3).get()),  // 2. 创建3秒租约并启动保活
        _lease_id(_keep_alive->Lease()) {}              // 3. 获取租约ID

    ~Registry() { _keep_alive->Cancel(); }  // 停止租约保活

    bool registry(const std::string& key,const std::string& val){
        // 向etcd写入键值对,绑定租约ID(成为临时节点),同步等待结果
        auto resp = _client->put(key,val,_lease_id).get();
        if(resp.is_ok() == false){  // 判断etcd操作是否成功
            LOG_ERROR("注册数据失败:{}",resp.error_message());
            return false;
        }
        return true;
    }

private:
    std::shared_ptr<etcd::Client> _client;  // etcd客户端智能指针
    std::shared_ptr<etcd::KeepAlive> _keep_alive;   // 租约保活智能指针,后台自动发心跳
    uint64_t _lease_id; // etcd租约ID,用于绑定键值对为「临时节点」

};


//服务发现客户端类
class Discovery{
public:
    using ptr = std::shared_ptr<Discovery>;
    // 服务变化的回调函数类型:参数为(服务key,服务val)
    using NotifyCallback = std::function<void(std::string,std::string)>;

    Discovery(const std::string& host,
        const std::string& basedir,
        const NotifyCallback& put_cb,
        const NotifyCallback& del_cb):
        _client(std::make_shared<etcd::Client>(host)),
        _put_cb(put_cb),_del_cb(del_cb){
            // 全量拉取:获取指定目录下的所有已有服务
            auto resp = _client->ls(basedir).get();
            if(resp.is_ok() == false){
                LOG_ERROR("获取服务信息数据失败:{}",resp.error_message());
            }
            int sz = resp.keys().size();
            for(int i=0;i<sz;++i){
                if(_put_cb){    // 回调非空则执行,初始化本地服务列表
                    _put_cb(resp.key(i),resp.value(i).as_string());
                }
            }
            // 增量监听:启动Watch,感知目录下的节点变化
            _watcher = std::make_shared<etcd::Watcher>(*_client.get(),basedir,
                        std::bind(&Discovery::callback,this,std::placeholders::_1),true);
        }
        
        ~Discovery(){ _watcher->Cancel(); } // 停止后台监听线程

private:
    void callback(const etcd::Response& resp){
        if(resp.is_ok() == false){
            LOG_ERROR("收到一个错误的事件通知:{}",resp.error_message());
            return;
        }
        for (auto const& ev : resp.events()) {
            if (ev.event_type() == etcd::Event::EventType::PUT) {
                if (_put_cb) _put_cb(ev.kv().key(), ev.kv().as_string());
                LOG_DEBUG("新增服务:{}-{}", ev.kv().key(), ev.kv().as_string());
            }else if (ev.event_type() == etcd::Event::EventType::DELETE_) {
                if (_del_cb) _del_cb(ev.prev_kv().key(), ev.prev_kv().as_string());
                LOG_DEBUG("下线服务:{}-{}", ev.prev_kv().key(), ev.prev_kv().as_string());
            }
        }
    }

private:
    NotifyCallback _put_cb; // 服务新增/更新的回调
    NotifyCallback _del_cb; // 服务下线的回调
    std::shared_ptr<etcd::Client> _client;  // etcd客户端
    std::shared_ptr<etcd::Watcher> _watcher;// 监听对象,后台运行


};



}
相关推荐
眷蓝天3 天前
Kubernetes etcd 技术指南
容器·kubernetes·etcd
Cat_Rocky3 天前
Kubernetes etcd备份恢复
容器·kubernetes·etcd
小义_4 天前
【Kubernetes】(二十)ETCD 备份与恢复
容器·kubernetes·etcd
古怪今人6 天前
etcd分布式键值存储系统 Windows下搭建etcd集群
数据库·分布式·etcd
开开心心就好8 天前
免费开源的网课教学屏幕画板工具
windows·eureka·计算机外设·word·excel·etcd·csdn开发云
@王先生110 天前
【K8S-ETCD初始化三节点集群】
前端·chrome·k8s·etcd·集群
xuefuhe12 天前
3节点etcd cluster的安装
etcd
米高梅狮子14 天前
13.ETCD 存储系统、生产环境 Kubernetes 集群部署和Kubernetes 集群升级
数据库·云原生·容器·架构·kubernetes·自动化·etcd
Aaron_Wjf16 天前
ETCD常用操作
etcd
赵文宇(温玉)18 天前
Docker Compose 安装 Etcd
docker·容器·etcd