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

[C++][第三方库][etcd]详细讲解

目录

  • 1.介绍
  • 2.安装
    • 1.安装etcd
    • 2.节点配置
    • 3.运行验证
  • 3.搭建服务注册发现中心
    • 0.前言
    • 1.etcd-cpp-apiv3
    • 2.客户端
      • 1.类与接口介绍
      • 2.使用示例


1.介绍

  • Etcd是一个golang编写的分布式、高可用的一致性键值存储系统,用于配置共享和服务发现
  • 它使用Raft一致性算法来保持集群数据的一致性,且客户端通过长连接watch功能,能够及时收到数据变化通知,相较于Zookeeper框架更加轻量化

2.安装

1.安装etcd

  • 安装sudo apt install etcd
  • 启动服务sudo systemctl start etcd
  • 设置开机自启sudo systemctl enable etcd

2.节点配置

  • 如果是单节点集群其实就可以不用进行配置,默认etcd的集群节点通信端口为2380, 客户端访问端口为2379
  • 若需要修改,则可以配置:/etc/default/etcd
#节点名称,默认为 "default" 
ETCD_NAME="etcd1" 
#数据目录,默认为 "${name}.etcd" 
ETCD_DATA_DIR="/var/lib/etcd/default.etcd" 
#用于客户端连接的 URL。 
ETCD_LISTEN_CLIENT_URLS="http://192.168.65.132:2379,http://127.0.0.1:2379" 
#用于客户端访问的公开,也就是提供服务的 URL 
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.65.132:2379,http://127.0.0.1:2379" 
#用于集群节点间通信的 URL。 
ETCD_LISTEN_PEER_URLS="http://192.168.65.132:2380" 
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.65.132:2380" 
#心跳间隔时间-毫秒 
ETCD_HEARTBEAT_INTERVAL=100 
#选举超时时间-毫秒 
ETCD_ELECTION_TIMEOUT=1000 #以下为集群配置,若无集群则需要注销 
#初始集群状态和配置--集群中所有节点 
#ETCD_INITIAL_CLUSTER="etcd1=http://192.168.65.132:2380,etcd2=http://192.168.65.132:2381,etcd3=http://192.168.65.132:2382" 
#初始集群令牌-集群的ID 
#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" 
#ETCD_INITIAL_CLUSTER_STATE="new" #以下为安全配置,如果要求SSL连接etcd的话,把下面的配置启用,并修改文件
路径 
#ETCD_CERT_FILE="/etc/ssl/client.pem" 
#ETCD_KEY_FILE="/etc/ssl/client-key.pem" 
#ETCD_CLIENT_CERT_AUTH="true" 
#ETCD_TRUSTED_CA_FILE="/etc/ssl/ca.pem" 
#ETCD_AUTO_TLS="true" 
#ETCD_PEER_CERT_FILE="/etc/ssl/member.pem" 
#ETCD_PEER_KEY_FILE="/etc/ssl/member-key.pem" 
#ETCD_PEER_CLIENT_CERT_AUTH="false" 
#ETCD_PEER_TRUSTED_CA_FILE="/etc/ssl/ca.pem" 
#ETCD_PEER_AUTO_TLS="true" 

3.运行验证

  • 命令行输入etcdctl put key "SnowK"
  • 如果以下出现报错,在/etc/profile默认声明环境变量ETCDCTL_API=3以确定etcd版本
    $ etcdctl put key "SnowK"
    No help topic for 'put'
    
  • 完成后,加载配置文件,并重新执行测试命令
    $ source /etc/profile 
    $ etcdctl put key "SnowK"
    OK 
    $ etcdctl get key 
    key 
    SnowK
    $ etcdctl del mykey 
    

3.搭建服务注册发现中心

0.前言

  • 使用etcd作为服务注册发现中心,需要定义服务的注册和发现逻辑
  • 通常涉及到以下几个操作
    • 服务注册:服务启动时,向etcd注册自己的地址和端口
    • 服务发现:客户端通过etcd获取服务的地址和端口,用于远程调用
    • 健康检查:服务定期向Etcd发送心跳,以维持其注册信息的有效性
  • 官方只维护了golangclient库,因此需要找到C/C++ 非官方的client 开发库

1.etcd-cpp-apiv3

  • etcd-cpp-apiv3是一个etcd的C++版本客户端API,它依赖于mipsasm, boost, protobuf, gRPC, cpprestsdk等库
  • Github
  • 依赖安装
    sudo apt-get install libboost-all-dev libssl-dev 
    sudo apt-get install libprotobuf-dev protobuf-compiler-grpc 
    sudo apt-get install libgrpc-dev libgrpc++-dev  
    sudo apt-get install libcpprest-dev 
    
  • API框架安装
    git clone https://github.com/etcd-cpp-apiv3/etcd-cpp-apiv3.git 
    cd etcd-cpp-apiv3 
    mkdir build && cd build 
    cmake .. -DCMAKE_INSTALL_PREFIX=/usr 
    make -j$(nproc) && sudo make install
    

2.客户端

1.类与接口介绍

  • Client对象:客户端操作句柄对象
    • 提供了新增,获取数据的接口
    • 提供了获取保活对象的接口,以及租约的接口
  • KeepAlive保活对象:一旦被析构,则无法保活,则租约数据失效被删除
    • 本身提供一个获取租约ID的接口
    • 作用:针对一个可以不断进行续租 --> 一直维持租约数据的有效性
  • Response对象:针对请求进行的响应
  • Value对象:存放键值对数据的对象
  • Watcher对象:进行数据变化通知的类
    //pplx::task 并行库异步结果对象 
    //阻塞方式   get(): 阻塞直到任务执行完成,并获取任务结果 
    //非阻塞方式 wait(): 等待任务到达终止状态,然后返回任务状态 namespace etcd 
    { class Value { bool is_dir()//判断是否是一个目录 std::string const& key() //键值对的key值 std::string const& as_string()//键值对的val值 int64_t lease() //用于创建租约的响应中,返回租约ID } //etcd会监控所管理的数据的变化,一旦数据产生变化会通知客户端 //在通知客户端的时候,会返回改变前的数据和改变后的数据 class Event { enum class EventType { PUT, //键值对新增或数据发生改变 DELETE_,//键值对被删除 INVALID, }; enum EventType event_type()  const Value& kv() const Value& prev_kv() } class Response { bool is_ok() std::string const& error_message() Value const& value()//当前的数值 或者 一个请求的处理结果 Value const& prev_value()//之前的数值 Value const& value(int index)// std::vector<Event> const& events();//触发的事件 } class KeepAlive { KeepAlive(Client const& client, int ttl, int64_t lease_id = 0); //返回租约ID int64_t Lease(); //停止保活动作 void Cancel(); } class Client { // etcd_url: "http://127.0.0.1:2379" Client(std::string const& etcd_url, std::string const& load_balancer = "round_robin"); //新增一个键值对 pplx::task<Response> put(std::string const& key,  std::string const& value); //新增带有租约的键值对 (一定时间后,如果没有续租,数据自动删除) pplx::task<Response> put(std::string const& key,  std::string const& value, const int64_t leaseId); //获取一个指定key目录下的数据列表 pplx::task<Response> ls(std::string const& key); //创建并获取一个存活ttl时间的租约 pplx::task<Response> leasegrant(int ttl); //获取一个租约保活对象,其参数ttl表示租约有效时间 pplx::task<std::shared_ptr<KeepAlive>> leasekeepalive(int ttl); //撤销一个指定的租约 pplx::task<Response> leaserevoke(int64_t lease_id); //数据锁 pplx::task<Response> lock(std::string const& key); } class Watcher { Watcher(Client const& client,  std::string const& key, //要监控的键值对key std::function<void(Response)> callback, //发生改变后的回调 bool recursive = false); //是否递归监控目录下的所有数据改变 Watcher(std::string const& address,  std::string const& key, std::function<void(Response)> callback,  bool recursive = false); //阻塞等待,直到监控任务被停止 bool Wait(); bool Cancel(); }
    }
    

2.使用示例

  • makefile
    all: get putget: get.ccg++ -o $@ $^ -std=c++17 -letcd-cpp-api -lcpprestput: put.ccg++ -o $@ $^ -std=c++17 -letcd-cpp-api -lcpprest.PHONY:clean
    clean:rm get put
    
  • get.cc
    #include <iostream>
    #include <thread>
    #include <etcd/Client.hpp>
    #include <etcd/KeepAlive.hpp>
    #include <etcd/Response.hpp>
    #include <etcd/Watcher.hpp>
    #include <etcd/Value.hpp>void CallBack(const etcd::Response& resp)
    {if(resp.is_ok() == false){std::cout << "收到一个错误的事件通知:" << resp.error_message() << std::endl;return;}else{for(const auto& ev : resp.events()){if(ev.event_type() == etcd::Event::EventType::PUT){std::cout << "服务信息发生了改变:" << std::endl;std::cout << "当前的值:" << ev.kv().key() << "-" << ev.kv().as_string() << std::endl;std::cout << "原来的值:" << ev.prev_kv().key() << "-" << ev.prev_kv().as_string() << std::endl;}else if(ev.event_type() == etcd::Event::EventType::DELETE_){std::cout << "服务信息下线被删除:\n";std::cout << "当前的值:" << ev.kv().key() << "-" << ev.kv().as_string() << std::endl;std::cout << "原来的值:" << ev.prev_kv().key() << "-" << ev.prev_kv().as_string() << std::endl;}}}
    }int main(int argc, char* argv[])
    {std::string etcd_host = "http://127.0.0.1:2379";// 实例化客户端对象etcd::Client client(etcd_host);// 获取指定的键值对信息// ls() -> 获取一个指定key目录下的数据列表auto resp = client.ls("/service").get();if(resp.is_ok() == false){std::cout << "获取键值对数据失败: " << resp.error_message() << std::endl;return -1;}int sz = resp.keys().size();for (int i = 0; i < sz; i++){std::cout << resp.value(i).as_string() << "可以提供" << resp.key(i) << "服务" << std::endl;}// 实例化一个键值对事件监控对象// true: 是否递归监控该目录auto watcher = etcd::Watcher(client, "/service", CallBack, true);watcher.Wait();return 0;
    }
    
  • put.cc
    #include <iostream>
    #include <thread>
    #include <etcd/Client.hpp>
    #include <etcd/KeepAlive.hpp>
    #include <etcd/Response.hpp>int main(int argc, char* argv[])
    {std::string etcd_host = "http://127.0.0.1:2379";// 实例化客户端对象etcd::Client client(etcd_host);// 获取租约保活对象 --> 伴随着创建一个指定有效时长的租约auto keep_alive = client.leasekeepalive(3).get();// 获取租约IDauto lease_id = keep_alive->Lease();// 向etcd新增数据auto resp1 = client.put("/service/user", "127.0.0.1:3366", lease_id).get();if(resp1.is_ok() == false){std::cout << "新增数据失败: " << resp1.error_message() << std::endl;return -1;}auto resp2 = client.put("/service/friend", "127.0.0.1:6633").get();if (resp2.is_ok() == false){std::cout << "新增数据失败: " << resp2.error_message() << std::endl;return -1;}std::this_thread::sleep_for(std::chrono::seconds(10));return 0;
    }
    
  • 运行结果
    127.0.0.1:6633可以提供/service/friend服务
    127.0.0.1:3366可以提供/service/user服务
    服务信息下线被删除:
    当前的值:/service/user-
    原来的值:/service/user-127.0.0.1:3366
    

http://www.mrgr.cn/news/42266.html

相关文章:

  • (16)MATLAB仿真Nakagami-m分布1
  • java基础 day2
  • 【Node.js】内置模块FileSystem的保姆级入门讲解
  • 【CKA】十二、持久化存储卷PersistentVolume
  • JSON 全知全解:深入探索 JSON 的奥秘
  • 【力扣 | SQL题 | 每日四题】力扣1581, 1811, 1821, 1831
  • Linux基础命令top详解
  • 华为OD机试真题---第k个排列
  • Vue根实例、实例总结
  • 【MAUI】内容页ShellContent
  • 官方證實 iPhone 上的 Apple Intelligence 需用到 4GB 儲存空間
  • Linux基础命令ps详解
  • 二叉查找一>x 的平方根
  • 基于SpringBoot+Vue+MySQL的校园招聘管理系统
  • Linux shell编程学习笔记85:fold命令——让文件瘦身塑形显示
  • 认知杂谈95《君子藏器于身,待时而动》》
  • 探索蛋白质相互作用的新视角:图神经网络在预测中的应用
  • day03 笔试练习
  • SpringBoot整合QQ邮箱
  • 酒店生态发展旅游四个一体化建设-—未来之窗行业应用跨平台架构