即时通讯项目--(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;// 监听对象,后台运行


};



}
相关推荐
小小小米粒8 天前
k8s流程创建清单
服务器·前端·etcd
ai产品老杨9 天前
打破芯片壁垒:基于Docker与K8s的GB28181/RTSP异构AI视频平台架构实战
人工智能·docker·eureka·时序数据库·etcd
weixin_3954489123 天前
cursor日志0224
eureka·flink·etcd
weixin_3954489123 天前
dataset.py_0224_cursor
eureka·flink·etcd
认真的薛薛1 个月前
6.k8s中Jobs-CronJobs-configmap-备份etcd
容器·kubernetes·etcd
Dovis(誓平步青云)1 个月前
《MySQL 事务深度解析:从 ACID 到实战,守住数据一致性的最后防线》
数据库·mysql·flink·etcd·功能详解
数据知道1 个月前
PostgreSQL:Patroni 高可用架构,基于etcd的自动故障转移集群
postgresql·架构·etcd
_Johnny_1 个月前
ETCD 配额/空间告警模拟方案
网络·数据库·etcd
_Johnny_1 个月前
ETCD 配额/空间告警模拟脚本
数据库·chrome·etcd
清风~徐~来2 个月前
【视频点播系统】Etcd-SDK 介绍及使用
数据库·etcd