玉溪市网站建设_网站建设公司_React_seo优化
2026/1/20 8:07:43 网站建设 项目流程

最近在搭后台项目环境时,接触到了ETCD
又是新组件,又是一堆依赖库!
不过跑通一遍样例后,才发现它的定位非常清晰 ——分布式键值对注册中心

这篇就简单记录一下我对 ETCD 的理解,以及 C++ 客户端的基本使用方式。


一、ETCD 是干什么的?

一句话总结:

ETCD 是一个分布式键值对数据存储服务器。

它的特点是:
多台主机可以共享一套键值数据,并且数据变化可以被实时感知。

举个直观的例子:

  • 主机 A 在 ETCD 上写入:name -> A
  • 主机 B 去查name,也能得到A
  • 主机 A 把name改成B
  • 主机 B 立刻收到通知:值从 A 变成了 B

所以它非常适合用来做服务注册与发现


二、长连接与租约(Lease)机制

ETCD 里有一个很重要的概念:租约(Lease)

你可以这样理解:

客户端向服务器“租”一个 ID,并定期续租。
只要租约还在,和这个租约绑定的数据就有效。
一旦客户端不再续租(程序退出或崩溃),数据自动过期删除。

我自己的理解更形象一点:

客户端就像在 ETCD 服务器上“付房租”。
一直交房租 → 数据一直存在
不交房租 → 数据被清理
其他客户端会收到通知:这个数据没了

这正好可以用来判断某个服务到底还在线还是已经下线


三、ETCD 与 C++ 客户端环境安装

这一块我一开始也有点蒙:
我明明已经安装了 etcd,为什么后面还要装一堆 boost、protobuf、grpc 之类的库?

后来才理清:

etcd 本体 = 服务器程序
etcd-cpp-apiv3 = C++ 客户端接口库

前者负责存储键值数据
后者负责让我在 C++ 代码里能调用 ETCD 的接口

所以需要分两部分安装。

1)安装 ETCD 服务端

先安装 etcd 可执行程序:

etcd --version

能看到版本号说明安装成功。

启动方式(开发阶段直接前台运行即可):

etcd

默认监听地址:

http://127.0.0.1:2379

2)安装 etcd-cpp-apiv3 所需依赖

因为 etcd-cpp-apiv3 底层是通过 gRPC + protobuf + boost + cpprestsdk 实现的,
所以要先安装这些基础库:

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

这一步的作用很简单:

为 C++ 调用 ETCD 的 API 准备底层通信与序列化环境

3)安装 etcd-cpp-apiv3 客户端库

接着安装 C++ 客户端接口库:

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

安装完成后,就可以在代码里直接:

#include “etcd/Client.hpp”

说明 C++ 客户端接口已经就绪。

4)最后环境关系图

到这里整个结构就很清晰了:

你的 C++ 代码

etcd-cpp-apiv3 (C++ 客户端 API)

gRPC + protobuf + boost + cpprestsdk

ETCD 服务端 (127.0.0.1:2379)

这样你的代码才能真正通过网络去访问 ETCD 服务器。

小结一下

etcd = 键值存储服务器程序

etcd-cpp-apiv3 = C++ 调用接口封装

依赖库 = 支撑网络通信与序列化

三者配齐后,后面的 put / get / watch 示例代码才能正常运行。

四、几个核心对象理解

结合 C++ 客户端 API,我目前主要用到这几个对象:

Client 对象

提供最基本的接口:

  • 新增键值对
  • 获取键值对
  • 删除键值对

也就是所有操作 ETCD 的入口。


KeepAlive 对象

它是对Lease / 续租的封装。

作用:

  • 创建租约 ID
  • 自动帮你续租
  • 只要 KeepAlive 对象存在 → 数据不会过期
  • 一旦对象释放 → 租约失效 → 数据自动删除

Response 对象

所有请求都会返回 Response,用来:

  • 判断请求是否成功
  • 获取返回的数据
  • 获取事件变化内容

Watcher 对象

对某个 Key 或前缀进行监听。

一旦数据发生变化:

  • PUT(新增 / 修改)
  • DELETE(删除)

就会触发回调函数通知客户端。


五、ETCD 在项目中的作用

我的项目里,ETCD 的核心目的就是:

让所有节点知道当前有哪些服务在线。

服务端启动:

  • 向 ETCD 注册自己的服务信息
  • 绑定租约
  • 定期续租

客户端启动:

  • Watch/service前缀
  • 一旦有新增 / 删除服务,立即收到通知

这样就能实现自动感知服务上线和下线


六、样例代码

下面是我当前跑通的两个样例:

  • put.cc:向 ETCD 写入数据并绑定租约
  • get.cc:获取数据并监听变化

put.cc

#include<iostream>#include"etcd/Client.hpp"#include"etcd/Response.hpp"#include"etcd/KeepAlive.hpp"#include<thread>intmain(intargc,char*argv[]){std::string etcd_host="http://127.0.0.1:2379";//实例化客户端对象etcd::Clientclient(etcd_host);//创建租约对象autokeep_alive=client.leasekeepalive(3).get();//获取租约对象autolease_id=keep_alive->Lease();//像etcd新增数据autoresp1=client.put("/service/user","111",lease_id).get();if(!resp1.is_ok()){std::cout<<"put key failed, error code: "<<resp1.error_code()<<", error message: "<<resp1.error_message()<<std::endl;return-1;}autoresp2=client.put("/service/haha","222").get();if(!resp2.is_ok()){std::cout<<"put key failed, error code: "<<resp2.error_code()<<", error message: "<<resp2.error_message()<<std::endl;return-1;}std::this_thread::sleep_for(std::chrono::seconds(10));return0;}

get.cc

#include"etcd/Client.hpp"#include"etcd/Response.hpp"#include"etcd/KeepAlive.hpp"#include"etcd/Watcher.hpp"#include<thread>#include<iostream>voidcallback(constetcd::Response&resp){if(!resp.is_ok()){std::cout<<"watch key failed, error code: "<<resp.error_code()<<", error message: "<<resp.error_message()<<std::endl;return;}for(autoconst&event:resp.events()){if(event.event_type()==etcd::Event::EventType::PUT){std::cout<<"服务信息发生了改变"<<std::endl;std::cout<<"原来的值为:"<<event.prev_kv().as_string()<<std::endl;std::cout<<"现在的值为:"<<event.kv().as_string()<<std::endl;}elseif(event.event_type()==etcd::Event::EventType::DELETE_){std::cout<<"服务信息被删除了"<<std::endl;std::cout<<"删除的值为:"<<event.prev_kv().as_string()<<std::endl;}}}intmain(intargc,char*argv[]){std::string etcd_host="http://127.0.0.1:2379";//实例化客户端etcd::Clientclient(etcd_host);//获取指定的键值对信息autoresp=client.ls("/service").get();if(!resp.is_ok()){std::cout<<"get key failed, error code: "<<resp.error_code()<<", error message: "<<resp.error_message()<<std::endl;return-1;}intsz=resp.keys().size();for(inti=0;i<sz;++i)std::cout<<resp.values()[i].as_string()<<"可以提供"<<resp.keys()[i]<<std::endl;//实例化一个键值对事件监控对象autowatcher=etcd::Watcher(client,"/service",callback,true);std::this_thread::sleep_for(std::chrono::seconds(10));return0;}

七、运行现象说明

运行顺序:

  1. 启动 ETCD 服务端
  2. 运行 get.cc(监听端)
  3. 运行 put.cc(注册端)

可以看到:

  • get.cc 启动时先打印已有服务
  • put.cc 写入数据
  • get.cc 立即收到 PUT 事件通知
  • put.cc 程序结束
  • 租约到期
  • get.cc 收到 DELETE 事件通知

这说明:

租约控制数据生命周期
Watcher 实现实时变更通知


八、总结一下

目前我对 ETCD 的理解可以概括成三点:

  • ETCD 是分布式键值存储服务器
  • Lease / KeepAlive 用来维持数据有效期
  • Watcher 用来感知数据变化

组合起来,就能实现:

服务注册 → 自动保活 → 自动下线 → 实时通知

这正是后台项目里服务注册与发现的基础能力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询