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

LinuxC++——etcd-cpp-api精简源代码函数参数查询参考

etcd封装

  • etcd框架
    • etcd::Client类
    • 一、构造函数:客户端初始化
      • 1. 基础构造:无认证、普通连接
    • 二、核心功能函数:etcd 操作接口
      • 1. 键值基础操作:CRUD
        • (1)读取键值:`get`/`ls`
        • (2)写入键值:`set`/`add`/`put`/`modify`
        • (3)删除键值:`rm`/`rmdir`
      • 2. 租约操作:`leasegrant`/`leaserevoke`/`leasekeepalive`
      • 3. 监听操作:`watch`
      • 4. 精简化参考源代码
    • etcd::Response类
      • 1. 静态创建函数(create 模板系列)
      • 2. 响应状态查询函数
      • 3. 响应数据获取函数(基本信息)
      • 4. 响应数据获取函数(键值相关)
      • 5. 响应数据获取函数(键列表相关)
      • 6. 响应数据获取函数(高级功能相关)
      • 7. 响应数据获取函数(集群信息)
      • 8. 构造函数与拷贝构造函数
      • 9. 精简化参考源代码
    • etcd::Value类与Event类
      • 1. etcd::Value 类(键值对数据载体)
      • 2. etcd::Event 类(监听事件载体)
      • 3. 精简化参考源代码
      • etcd::Watcher
      • 1. etcd::Watcher 核心函数与参数表格
      • 2. 精简化参考源代码
      • 3. 参考使用
    • etcd::KeepAlive
      • 1. etcd::KeepAlive 核心函数与参数表格
      • 2. 精简版 etcd::KeepAlive 头文件(初学者友好)
      • 3. 给初学者的关键说明
    • pplx::task
      • 1. 模板类 `task<_ReturnType>` 核心函数与参数表格

etcd框架

etcd::Client类

一、构造函数:客户端初始化

构造函数的核心作用是建立与 etcd 集群的连接,支持普通连接、认证(用户名密码)、SSL 加密、自定义 gRPC 参数等场景,同时提供静态工厂方法(WithXXX)简化初始化。

1. 基础构造:无认证、普通连接

构造函数签名核心参数功能说明
Client(std::string const & etcd_url, std::string const & load_balancer = "round_robin")- etcd_url:etcd 集群地址,支持多个地址(用 ,; 分隔,如 "http://127.0.0.1:2379,http://127.0.0.1:2380")- load_balancer:负载均衡策略,默认 round_robin(轮询),可选值:round_robin(轮询)、pick_first(优先第一个)、grpclbxds初始化无认证的异步客户端,指定集群地址和负载均衡策略
Client(std::string const & etcd_url, grpc::ChannelArguments const & arguments)- arguments:gRPC 通道自定义参数(如超时、最大重试次数等)支持通过 gRPC 原生参数精细化配置连接(如设置 TLS 选项、通道缓存大小等)
静态工厂方法 static Client* WithUrl(...)同上述构造函数参数

二、核心功能函数:etcd 操作接口

在学习函数前,先明确 2 个基础概念:

  1. 异步任务(pplx::task):所有核心函数的返回值都是 pplx::task<Response>,这是微软 PPL 库的异步任务类型 —— 函数调用后不会 “阻塞等待结果”,而是返回一个 “任务对象”,通过 .then().get()(阻塞)获取最终结果。
  2. Response 对象:存储 etcd 操作的结果(成功 / 失败、键值数据、版本号等),常用方法如 IsSuccess()(判断是否成功)、value()(获取键对应的值)、index()(获取操作的版本号)。

1. 键值基础操作:CRUD

(1)读取键值:get/ls
函数签名核心参数功能说明
pplx::task<Response> get(std::string const & key)- key:要读取的键(如 /config/db/host读取单个键的 value 和元数据(版本号、租约 ID 等)
pplx::task<Response> ls(std::string const & key)- key:目录键(如 /config/db列出目录下的所有子键(类似文件系统 ls
pplx::task<Response> ls(std::string const & key, size_t const limit)- limit:结果数量限制分页列出目录下的子键,避免结果过多
pplx::task<Response> ls(std::string const & key, std::string const & range_end)- range_end:键范围结束(左闭右开 [key, range_end)
(2)写入键值:set/add/put/modify
函数签名核心参数功能说明
pplx::task<Response> set(std::string const & key, std::string const & value, int ttl = 0)- key/value:键 / 值- ttl:键的有效期(秒,0 表示永久)写入键值:键存在则更新,不存在则创建(覆盖式写入)
pplx::task<Response> set(std::string const & key, std::string const & value, int64_t leaseId)- leaseId:租约 ID绑定租约写入:租约过期后键自动删除
pplx::task<Response> add(std::string const & key, std::string const & value, int ttl = 0)set仅创建键:键已存在则操作失败(原子性 “新增”)
pplx::task<Response> put(std::string const & key, std::string const & value)set(无 TTL / 租约)简化版写入(仅键值,无过期逻辑),等价于 set(key, value, 0)
pplx::task<Response> modify(std::string const & key, std::string const & value, int ttl = 0)set仅更新键:键不存在则操作失败(原子性 “更新”)
pplx::task<Response> modify_if(std::string const & key, std::string const & value, std::string const & old_value, int ttl = 0)- old_value:预期的旧值条件更新:仅当键的当前值等于 old_value 时更新(避免并发覆盖)
pplx::task<Response> modify_if(std::string const & key, std::string const & value, int64_t old_index, int ttl = 0)- old_index:预期的旧版本号(mod_revision条件更新:仅当键的当前版本号等于 old_index 时更新(更严谨的并发控制)
(3)删除键值:rm/rmdir
函数签名核心参数功能说明
pplx::task<Response> rm(std::string const & key)- key:要删除的单个键删除非目录键,键不存在则操作失败
pplx::task<Response> rm_if(std::string const & key, std::string const & old_value)- old_value:预期的旧值条件删除:仅当键的当前值等于 old_value 时删除
pplx::task<Response> rm_if(std::string const & key, int64_t old_index)- old_index:预期的旧版本号条件删除:仅当键的当前版本号等于 old_index 时删除
pplx::task<Response> rmdir(std::string const & key, bool recursive = false)- key:目录键- recursive:是否递归删除(true 删整个子树,false 仅删空目录)删除目录:类似文件系统 rmdir
pplx::task<Response> rmdir(std::string const & key, std::string const & range_end)- range_end:键范围结束删除指定范围的键(左闭右开 [key, range_end)),批量删除场景

2. 租约操作:leasegrant/leaserevoke/leasekeepalive

etcd 租约用于管理键的生命周期:租约过期后,所有绑定该租约的键自动删除。

函数签名核心参数功能说明
pplx::task<Response> leasegrant(int ttl)- ttl:租约有效期(秒)申请新租约,返回租约 ID(lease_id
pplx::task<std::shared_ptr<KeepAlive>> leasekeepalive(int ttl)- ttl:租约有效期申请租约并自动续期(返回 KeepAlive 实例,销毁时停止续期)
pplx::task<Response> leaserevoke(int64_t lease_id)- lease_id:要注销的租约 ID手动注销租约,绑定该租约的键立即删除
pplx::task<Response> leasetimetolive(int64_t lease_id)- lease_id:租约 ID查询租约剩余有效期

3. 监听操作:watch

监听键或目录的变化(新增、更新、删除),异步获取变化事件。

函数签名核心参数功能说明
pplx::task<Response> watch(std::string const & key, bool recursive = false)- key:监听的键 / 目录- recursive:是否递归监听目录(true 监听子键变化)实时监听键 / 目录的变化,首次调用从当前版本开始
pplx::task<Response> watch(std::string const & key, int64_t fromIndex, bool recursive = false)- fromIndex:起始版本号从指定版本号开始监听(支持 “回溯” 监听历史变化)
pplx::task<Response> watch(std::string const & key, std::string const & range_end)- range_end:键范围结束

4. 精简化参考源代码

#ifndef __ETCD_CLIENT_CORE_HPP__
#define __ETCD_CLIENT_CORE_HPP__// 基础依赖库头文件
#include <chrono>
#include <memory>
#include <string>// 异步任务库(etcd 异步操作依赖)
#include "pplx/pplxtasks.h"// 响应结果封装类(与 Client 强关联)
#include "etcd/Response.hpp"
// 同步客户端类(异步 Client 基于同步 Client 实现)
#include "etcd/SyncClient.hpp"
// etcd v3 操作常量定义(如操作类型、负载均衡策略)
#include "etcd/v3/action_constants.hpp"namespace etcd
{/*** @brief etcd 异步客户端核心类* 负责与 etcd 服务器建立连接,提供所有异步操作接口(如增删改查、监听、锁、选举等)* 所有操作返回 pplx::task<Response>,需通过异步方式获取结果*/class Client{public:// =========================================================================// 核心1:客户端构造与创建接口(初始化连接,支持多种认证/连接方式)// =========================================================================/*** @brief 基于已有的同步客户端构造异步客户端* @param sync_client 已初始化的 SyncClient 对象指针(外部需确保生命周期)*/Client(SyncClient *client);/*** @brief 静态方法:基于同步客户端创建异步客户端(返回指针)* @param sync_client 已初始化的 SyncClient 对象指针* @return 异步 Client 对象指针(需外部管理生命周期)*/static Client* WithClient(SyncClient *client);/*** @brief 基础构造:通过 etcd 服务地址创建客户端(支持负载均衡)* @param etcd_url etcd 服务地址,多个地址用 ',' 或 ';' 分隔(如 "http://127.0.0.1:2379,http://127.0.0.1:2380")* @param load_balancer 负载均衡策略(可选,默认 round_robin,支持 pick_first/grpclb/xds)*/Client(std::string const & etcd_url,std::string const & load_balancer = "round_robin");/*** @brief 静态方法:通过 etcd 服务地址创建客户端(返回指针)* @param etcd_url etcd 服务地址(格式同上)* @param load_balancer 负载均衡策略(可选,默认 round_robin)* @return 异步 Client 对象指针*/static Client *WithUrl(std::string const & etcd_url,std::string const & load_balancer = "round_robin");/*** @brief 带认证构造:通过用户名密码创建客户端(支持负载均衡)* @param etcd_url etcd 服务地址(格式同上)* @param username etcd 认证用户名* @param password etcd 认证密码* @param auth_token_ttl 认证令牌有效期(秒,默认 300,对应 etcd --auth-token-ttl 配置)* @param load_balancer 负载均衡策略(可选,默认 round_robin)*/Client(std::string const & etcd_url,std::string const & username,std::string const & password,int const auth_token_ttl = 300,std::string const & load_balancer = "round_robin");/*** @brief 静态方法:带认证创建客户端(返回指针)* @param etcd_url etcd 服务地址(格式同上)* @param username etcd 认证用户名* @param password etcd 认证密码* @param auth_token_ttl 认证令牌有效期(秒,默认 300)* @param load_balancer 负载均衡策略(可选,默认 round_robin)* @return 异步 Client 对象指针*/static Client *WithUser(std::string const & etcd_url,std::string const & username,std::string const & password,int const auth_token_ttl = 300,std::string const & load_balancer = "round_robin");/*** @brief SSL 加密构造:通过 SSL 证书创建客户端(支持负载均衡)* @param etcd_url etcd 服务地址(格式同上,需用 https 协议)* @param ca SSL 根证书文件路径(验证服务端身份)* @param cert SSL 客户端证书文件路径(可选,空表示不验证客户端)* @param privkey SSL 客户端私钥文件路径(可选,空表示不验证客户端)* @param target_name_override SSL 目标名称覆盖(可选,无 DNS 时使用,需在证书 SAN 中存在)* @param load_balancer 负载均衡策略(可选,默认 round_robin)*/Client(std::string const & etcd_url,std::string const & ca,std::string const & cert = "",std::string const & privkey = "",std::string const & target_name_override = "",std::string const & load_balancer = "round_robin");/*** @brief 静态方法:SSL 加密创建客户端(返回指针)* @param etcd_url etcd 服务地址(格式同上,https 协议)* @param ca SSL 根证书文件路径* @param cert SSL 客户端证书文件路径(可选)* @param privkey SSL 客户端私钥文件路径(可选)* @param target_name_override SSL 目标名称覆盖(可选)* @param load_balancer 负载均衡策略(可选,默认 round_robin)* @return 异步 Client 对象指针*/static Client *WithSSL(std::string const & etcd_url,std::string const & ca,std::string const & cert = "",std::string const & privkey = "",std::string const & target_name_override = "",std::string const & load_balancer = "round_robin");/*** @brief 析构函数:释放客户端资源(如连接、认证令牌等)*/~Client();// =========================================================================// 核心2:基础键值操作接口(增删改查,最常用)// =========================================================================/*** @brief 获取 etcd 服务当前的 HEAD 版本(集群最新数据版本)* @return 异步任务,结果包含版本信息(Response 中通过 index() 获取)*/pplx::task<Response> head();/*** @brief 读取指定键的值* @param key 要读取的键名(如 "/config/db/host")* @return 异步任务,结果包含键的当前值(Response 中通过 value() 获取)*/pplx::task<Response> get(std::string const & key);/*** @brief 设置键的值(键不存在则创建,存在则覆盖)* @param key 要设置的键名* @param value 要设置的值* @param ttl 键的过期时间(秒,0 表示永久,可选)* @return 异步任务,结果包含设置后的键值信息*/pplx::task<Response> set(std::string const & key, std::string const & value, int ttl = 0);/*** @brief 设置键的值(绑定租约)* @param key 要设置的键名* @param value 要设置的值* @param leaseId 租约 ID(通过 leasegrant() 获取,租约过期后键自动删除)* @return 异步任务,结果包含设置后的键值信息*/pplx::task<Response> set(std::string const & key, std::string const & value, int64_t leaseId);/*** @brief 新增键(仅键不存在时成功,存在则失败)* @param key 要新增的键名* @param value 要设置的值* @param ttl 键的过期时间(秒,0 表示永久,可选)* @return 异步任务,结果包含新增后的键值信息(失败时 error_code() 非 0)*/pplx::task<Response> add(std::string const & key, std::string const & value, int ttl = 0);/*** @brief 删除指定键(仅非目录键)* @param key 要删除的键名* @return 异步任务,结果包含删除前的键值信息(Response 中通过 prev_value() 获取)*/pplx::task<Response> rm(std::string const & key);// =========================================================================// 核心3:目录/范围操作接口(批量处理键)// =========================================================================/*** @brief 列出目录下的所有键(非递归)* @param key 目录键名(如 "/config/db")* @return 异步任务,结果包含目录下的键列表(Response 中通过 keys()/values() 获取)*/pplx::task<Response> ls(std::string const & key);/*** @brief 列出指定键范围的所有键([key, range_end))* @param key 范围起始键* @param range_end 范围结束键(不包含)* @return 异步任务,结果包含范围内的键列表*/pplx::task<Response> ls(std::string const & key, std::string const &range_end);/*** @brief 删除目录(或键范围)* @param key 目录键名(或范围起始键)* @param recursive 是否递归删除(true 删整个子树,false 仅删空目录,可选)* @return 异步任务,结果包含删除的键信息*/pplx::task<Response> rmdir(std::string const & key, bool recursive = false);/*** @brief 删除指定键范围([key, range_end))* @param key 范围起始键* @param range_end 范围结束键(不包含)* @return 异步任务,结果包含删除的键信息*/pplx::task<Response> rmdir(std::string const & key, std::string const &range_end);// =========================================================================// 核心4:监听操作接口(实时监控键变化)// =========================================================================/*** @brief 监听指定键的变化(非递归)* @param key 要监听的键名* @param recursive 是否递归监听(true 监听整个子树,false 仅监听当前键,可选)* @return 异步任务,结果包含触发的事件(Response 中通过 events() 获取)*/pplx::task<Response> watch(std::string const & key, bool recursive = false);/*** @brief 从指定版本开始监听键的变化* @param key 要监听的键名* @param fromIndex 起始版本号(从该版本后的变化会被监听)* @param recursive 是否递归监听(可选,默认 false)* @return 异步任务,结果包含触发的事件*/pplx::task<Response> watch(std::string const & key, int64_t fromIndex, bool recursive = false);/*** @brief 监听指定键范围的变化([key, range_end))* @param key 范围起始键* @param range_end 范围结束键(不包含)* @return 异步任务,结果包含触发的事件*/pplx::task<Response> watch(std::string const & key, std::string const &range_end);// =========================================================================// 核心5:租约操作接口(键过期管理)// =========================================================================/*** @brief 申请租约(获取租约 ID)* @param ttl 租约有效期(秒)* @return 异步任务,结果包含租约 ID(Response 中通过 value() 或内部字段获取)*/pplx::task<Response> leasegrant(int ttl);/*** @brief 维持租约(自动续期,避免租约过期)* @param ttl 租约初始有效期(秒)* @return 异步任务,结果包含租约保持器(KeepAlive),需持有以持续续期*/pplx::task<std::shared_ptr<KeepAlive>> leasekeepalive(int ttl);/*** @brief 撤销租约(租约过期,绑定的键会被自动删除)* @param lease_id 要撤销的租约 ID* @return 异步任务,结果包含租约撤销状态*/pplx::task<Response> leaserevoke(int64_t lease_id);// =========================================================================// 核心6:分布式锁操作接口(集群并发控制)// =========================================================================/*** @brief 获取分布式锁(使用默认租约,自动续期)* @param key 锁键名(如 "/lock/db",同一键对应同一把锁)* @return 异步任务,结果包含锁键信息(成功时 is_ok() 为 true)*/pplx::task<Response> lock(std::string const &key);/*** @brief 获取分布式锁(指定租约有效期,自动续期)* @param key 锁键名* @param lease_ttl 租约有效期(秒,决定锁的最大持有时间)* @return 异步任务,结果包含锁键信息*/pplx::task<Response> lock(std::string const &key, int lease_ttl);/*** @brief 释放分布式锁* @param lock_key 锁键名(需与获取锁时的 key 一致)* @return 异步任务,结果包含锁释放状态*/pplx::task<Response> unlock(std::string const &lock_key);// =========================================================================// 核心7:客户端配置与工具接口// =========================================================================/*** @brief 设置 gRPC 操作超时时间* @tparam Rep 时间单位类型(默认微秒,如 std::chrono::seconds 表示秒)* @param timeout 超时时间(如 std::chrono::seconds(5) 表示 5 秒)*/template <typename Rep = std::micro>void set_grpc_timeout(std::chrono::duration<Rep> const &timeout) {this->client->set_grpc_timeout(timeout);}/*** @brief 获取当前 gRPC 操作超时时间* @return 超时时间(单位:微秒)*/std::chrono::microseconds get_grpc_timeout() const {return this->client->get_grpc_timeout();}/*** @brief 获取底层同步客户端(用于高级操作)* @return 同步客户端指针(无需外部释放,由 Client 管理)*/SyncClient* sync_client() const;private:bool own_client = true;          // 是否拥有同步客户端的所有权(决定析构时是否释放)SyncClient *client = nullptr;    // 底层同步客户端(异步操作的实际执行者)};
}#endif // __ETCD_CLIENT_CORE_HPP__

etcd::Response类

1. 静态创建函数(create 模板系列)

函数原型参数解释作用
template <typename T> static etcd::Response create(std::unique_ptr<T> call)callunique_ptr 包装的异步操作对象等待异步操作完成,解析响应并创建 Response 对象
template <typename T> static etcd::Response create(std::shared_ptr<T> call)callshared_ptr 包装的异步操作对象等待异步操作完成,解析响应并创建 Response 对象
template <typename T> static etcd::Response create(std::unique_ptr<T> call, std::function<void(Response)> callback)callunique_ptr 包装的异步操作对象callback:响应处理完成后的回调函数等待异步操作完成,执行回调后解析响应并创建 Response 对象
template <typename T> static etcd::Response create(std::function<std::unique_ptr<T>()> callfn)callfn:返回 unique_ptr<T> 的函数对象延迟创建异步操作对象,等待完成后解析响应并创建 Response 对象
template <typename T> static etcd::Response create(std::function<std::shared_ptr<T>()> callfn)callfn:返回 shared_ptr<T> 的函数对象延迟创建异步操作对象,等待完成后解析响应并创建 Response 对象

2. 响应状态查询函数

函数原型参数解释作用
bool is_ok() const无参数判断请求是否成功(成功返回 true
bool is_network_unavailable() const无参数判断错误是否为网络不可用(是则返回 true
int error_code() const无参数返回错误代码(0 表示成功)
bool is_grpc_timeout() const无参数判断是否为 gRPC 超时错误(是则返回 true
std::string const & error_message() const无参数返回错误信息的字符串描述

3. 响应数据获取函数(基本信息)

函数原型参数解释作用
std::string const & action() const无参数返回操作类型(如 get/set/delete 等)
int64_t index() const无参数返回 etcd 当前的索引值
std::chrono::microseconds const & duration() const无参数返回请求执行耗时(单位:微秒)

4. 响应数据获取函数(键值相关)

函数原型参数解释作用
Value const & value() const无参数返回当前值对象(适用于 get/set/modify 操作)
Value const & prev_value() const无参数返回修改前的值对象(适用于 set/modify/rm 操作)
Value const & value(int index) constindex:值在列表中的索引返回指定索引的值(适用于目录列表操作)
Values const & values() const无参数返回值列表(适用于目录操作)

5. 响应数据获取函数(键列表相关)

函数原型参数解释作用
Keys const & keys() const无参数返回键列表(适用于目录操作)
std::string const & key(int index) constindex:键在列表中的索引返回指定索引的键

6. 响应数据获取函数(高级功能相关)

函数原型参数解释作用
int64_t compact_revision() const无参数返回压缩版本号(用于 watch 操作取消场景,-1 表示未初始化)
std::string const & lock_key() const参数返回锁的键(用于锁操作)
std::string const & name() const无参数返回名称(用于选举操作)
std::vector<Event> const & events() const无参数返回 watch 到的事件列表

7. 响应数据获取函数(集群信息)

函数原型参数解释作用
uint64_t cluster_id() const无参数返回集群 ID
uint64_t member_id() const无参数返回成员 ID
uint64_t raft_term() const无参数返回当前 raft 任期

8. 构造函数与拷贝构造函数

函数原型参数解释作用
Response()无参数默认构造函数,初始化空响应
Response(const Response &)无参数(隐式传入被拷贝对象)拷贝构造函数,复制已有响应对象
Response(const etcdv3::V3Response& response, std::chrono::microseconds const& duration)response:etcd v3 响应对象duration:请求执行耗时从 v3 响应构建 Response 对象(受保护)
Response(int error_code, char const * error_message)error_code:错误代码error_message:错误信息直接通过错误码和信息构建 Response 对象(受保护)

9. 精简化参考源代码

#ifndef __ETCD_RESPONSE_CORE_HPP__
#define __ETCD_RESPONSE_CORE_HPP__// 基础依赖库头文件
#include <chrono>
#include <functional>
#include <memory>
#include <string>
#include <vector>// 引入键值数据载体头文件(实际项目中需确保路径正确)
#include "etcd/Value.hpp"// 提前声明etcd v3底层相关类(避免循环引用)
namespace etcdv3 {class AsyncWatchAction;class AsyncLeaseKeepAliveAction;class AsyncObserveAction;class V3Response;
}namespace etcd
{// 定义键列表类型:存储多个键的字符串集合typedef std::vector<std::string> Keys;/*** @brief etcd客户端请求的响应封装类* 所有etcd操作(如增删改查、监听、锁等)的结果,均通过此类返回*/class Response{public:// =========================================================================// 核心:Response对象创建接口(工厂方法,处理不同类型的异步操作)// =========================================================================/*** @brief 处理独占所有权的异步操作* @tparam T 异步操作类型(如AsyncGetAction、AsyncPutAction等)* @param call 独占所有权的异步操作对象(unique_ptr确保内存安全)* @return 封装好的Response对象*/template <typename T>static etcd::Response create(std::unique_ptr<T> call);/*** @brief 处理共享所有权的异步操作* @tparam T 异步操作类型* @param call 共享所有权的异步操作对象(shared_ptr支持多处引用)* @return 封装好的Response对象*/template <typename T>static etcd::Response create(std::shared_ptr<T> call);/*** @brief 带回调函数的异步操作处理* @tparam T 异步操作类型* @param call 独占所有权的异步操作对象* @param callback 操作完成后的回调函数(参数为Response,用于自定义结果处理)* @return 封装好的Response对象*/template <typename T>static etcd::Response create(std::unique_ptr<T> call,std::function<void(Response)> callback);/*** @brief 处理延迟创建的独占所有权异步操作* @tparam T 异步操作类型* @param callfn 生成异步操作对象的函数(延迟创建,灵活控制初始化时机)* @return 封装好的Response对象*/template <typename T>static etcd::Response create(std::function<std::unique_ptr<T>()> callfn);/*** @brief 处理延迟创建的共享所有权异步操作* @tparam T 异步操作类型* @param callfn 生成异步操作对象的函数* @return 封装好的Response对象*/template <typename T>static etcd::Response create(std::function<std::shared_ptr<T>()> callfn);// =========================================================================// 基础构造与拷贝接口// =========================================================================/*** @brief 默认构造函数* 初始化空的响应对象,后续需通过create方法或其他构造补充数据*/Response();/*** @brief 拷贝构造函数* 用于复制已有的Response对象(深拷贝,确保数据独立)* @param 待拷贝的Response对象*/Response(const Response &);// =========================================================================// 核心1:响应状态查询接口(判断操作成败与错误类型)// =========================================================================/*** @brief 判断请求是否成功* @return true:操作成功;false:操作失败(含网络错误、业务错误等)*/bool is_ok() const;/*** @brief 判断错误是否为网络不可用* @return true:网络不可用;false:非网络错误(如键不存在、权限不足等)*/bool is_network_unavailable() const;/*** @brief 获取错误代码* @return 错误码(0表示成功,非0对应具体错误类型,参考etcd官方错误码定义)*/int error_code() const;/*** @brief 判断是否为gRPC超时错误* @return true:gRPC请求超时;false:非超时错误*/bool is_grpc_timeout() const;/*** @brief 获取错误描述信息* @return 错误信息字符串(人类可读,如"key not found")*/std::string const & error_message() const;// =========================================================================// 核心2:基础操作元信息接口(获取操作类型、索引等)// =========================================================================/*** @brief 获取操作类型* @return 操作类型字符串(如"GET"、"PUT"、"DELETE"、"WATCH"等)*/std::string const & action() const;/*** @brief 获取etcd当前索引值* @return 索引值(etcd用于版本控制,每次数据变更递增)*/int64_t index() const;/*** @brief 获取请求执行耗时* @return 耗时(单位:微秒,含请求发送到响应解析的完整时间)*/std::chrono::microseconds const & duration() const;// =========================================================================// 核心3:键值数据接口(获取单键值、多键值、历史值)// =========================================================================/*** @brief 获取当前键值对象(单键操作)* @return 当前键值对象(适用于GET、PUT、MODIFY等单键操作)*/Value const & value() const;/*** @brief 获取操作前的旧键值对象* @return 旧键值对象(适用于PUT、MODIFY、DELETE等变更操作)*/Value const & prev_value() const;/*** @brief 获取指定索引的键值对象(多键操作)* @param index 键值在列表中的索引(从0开始)* @return 对应索引的键值对象(适用于LS等目录列表操作)*/Value const & value(int index) const;/*** @brief 获取多键值列表* @return 键值对象列表(适用于LS等目录列表操作)*/Values const & values() const;// =========================================================================// 核心4:键列表接口(获取多键名称)// =========================================================================/*** @brief 获取多键名称列表* @return 键名称字符串列表(适用于LS等目录列表操作)*/Keys const & keys() const;/*** @brief 获取指定索引的键名称* @param index 键在列表中的索引(从0开始)* @return 对应索引的键名称(适用于LS等目录列表操作)*/std::string const & key(int index) const;// =========================================================================// 核心5:高级功能接口(监听、锁、选举相关)// =========================================================================/*** @brief 获取watch操作的压缩版本号* @return 压缩版本号(-1表示未初始化,仅watch被取消时有效)*/int64_t compact_revision() const;/*** @brief 获取锁的键名称* @return 锁键字符串(适用于LOCK、UNLOCK操作)*/std::string const & lock_key() const;/*** @brief 获取选举相关的名称* @return 名称字符串(适用于选举campaign操作)*/std::string const & name() const;/*** @brief 获取watch操作的事件列表* @return 事件对象列表(每个事件含类型、新旧值,适用于WATCH操作)*/std::vector<Event> const & events() const;// =========================================================================// 核心6:集群信息接口(获取集群、成员、任期信息)// =========================================================================/*** @brief 获取当前集群ID* @return 集群唯一标识ID*/uint64_t cluster_id() const;/*** @brief 获取当前成员ID* @return 集群成员唯一标识ID*/uint64_t member_id() const;/*** @brief 获取当前Raft任期号* @return Raft任期号(etcd集群一致性协议相关,任期变更代表 leader 切换)*/uint64_t raft_term() const;protected:// =========================================================================// 受保护构造:仅内部/友元类使用(初学者无需关注)// =========================================================================/*** @brief 从etcd v3底层响应构建Response* @param response etcd v3底层响应对象* @param duration 请求执行耗时*/Response(const etcdv3::V3Response& response, std::chrono::microseconds const& duration);/*** @brief 直接通过错误码和错误信息构建Response* @param error_code 错误码* @param error_message 错误描述信息*/Response(int error_code, char const * error_message);// =========================================================================// 成员变量:存储响应数据(初学者了解即可,通过接口访问)// =========================================================================int                 _error_code;          // 错误码(0=成功)std::string         _error_message;        // 错误描述int64_t             _index;                // etcd当前索引std::string         _action;               // 操作类型Value               _value;                // 当前键值Value               _prev_value;           // 旧键值Values              _values;               // 多键值列表Keys                _keys;                 // 多键名称列表int64_t             _compact_revision = -1;// watch压缩版本号std::string         _lock_key;             // 锁键std::string         _name;                 // 选举相关名称std::vector<Event>  _events;               // watch事件列表std::chrono::microseconds _duration;       // 请求耗时uint64_t            _cluster_id;           // 集群IDuint64_t            _member_id;            // 成员IDuint64_t            _raft_term;            // Raft任期// 友元类:允许这些类访问内部成员(初学者无需关注)friend class Client;friend class SyncClient;friend class etcdv3::AsyncWatchAction;friend class etcdv3::AsyncLeaseKeepAliveAction;friend class etcdv3::AsyncObserveAction;};
}#endif // __ETCD_RESPONSE_CORE_HPP__

etcd::Value类与Event类

1. etcd::Value 类(键值对数据载体)

函数原型参数解释作用
bool is_dir() const无参数判断当前键是否为目录(true 表示目录,false 表示普通键)
std::string const & key() const无参数返回键的完整绝对路径(如 /config/db/host
std::string const & as_string() const无参数返回键的字符串形式值(仅普通键有效,目录键返回空)
int64_t created_index() const无参数返回键的创建索引(etcd 全局递增的版本号,标记创建时间)
int64_t modified_index() const无参数返回键的最后修改索引(标记最近一次更新的时间)
int64_t version() const无参数返回键的版本号(创建时为 1,每次更新递增 1)
int ttl() const无参数返回键的过期时间(TTL,单位:秒,0 表示永久有效)
int64_t lease() const无参数返回键绑定的租约 ID(0 表示未绑定租约,租约过期后键自动删除)

2. etcd::Event 类(监听事件载体)

函数原型参数解释作用
enum EventType event_type() const无参数返回事件类型:- PUT:键新增或修改- DELETE_:键删除- INVALID:无效事件
bool has_kv() const无参数判断事件是否包含变更后的键值PUT 事件为 trueDELETE_ 事件为 false
bool has_prev_kv() const无参数判断事件是否包含变更前的键值(修改 / 删除事件可能为 true,新增事件为 false
const Value &kv() const无参数返回变更后的键值对象(仅 has_kv()true 时有效)
const Value &prev_kv() const无参数返回变更前的键值对象(仅 has_prev_kv()true 时有效)

补充说明

  • Values 类型typedef std::vector<Value> Values,用于存储多个键值对(如目录下的所有键)。
  • Events 类型typedef std::vector<Event> Events,用于存储多个监听事件(如一次 watch 操作触发的所有变更)。
  • 这两个类的对象通常通过 Response 类的接口(如 values()events())获取,不直接由用户创建。

3. 精简化参考源代码

#ifndef __ETCD_VECTOR_CORE_HPP__
#define __ETCD_VECTOR_CORE_HPP__// 基础依赖库头文件
#include <string>
#include <vector>// 提前声明底层依赖类(避免循环引用,初学者理解为“内部用到的其他模块类”)
namespace etcdv3 { class KeyValue; }
namespace mvccpb { class KeyValue; class Event; }namespace etcd
{// 提前声明友元类(这些类可访问 Value/Event 的内部数据,初学者无需深入)class Client;class SyncClient;class Response;// =========================================================================// 核心1:etcd::Value 类(键值对数据载体)// =========================================================================/*** @brief etcd 键值对的核心封装类* 存储单个键的完整信息(键名、值、版本、生命周期等),是 Response 中承载数据的基础单元*/class Value{public:/*** @brief 判断当前键是否为目录(etcd 中目录是特殊的键类型)* @return true = 是目录(此时 as_string() 获取的值无意义);false = 普通键*/bool is_dir() const;/*** @brief 获取键的完整路径(绝对路径,如 "/config/db/host")* @return 键名字符串(不可修改)*/std::string const & key() const;/*** @brief 获取键的字符串形式的值(仅普通键有效,目录键返回空)* @return 键值字符串(不可修改)*/std::string const & as_string() const;/*** @brief 获取键的创建索引(etcd 中每次数据变更都会生成唯一索引,创建时的索引即为此值)* @return 创建索引(正整数,值越大表示创建时间越晚)*/int64_t created_index() const;/*** @brief 获取键的最后修改索引(键值更新时的索引,可用于版本控制)* @return 最后修改索引(正整数,值越大表示修改时间越晚)*/int64_t modified_index() const;/*** @brief 获取键的版本号(键创建时为 1,每次更新递增 1)* @return 版本号(正整数,用于判断键是否被修改)*/int64_t version() const;/*** @brief 获取键的过期时间(TTL,Time To Live)* @return 过期时间(秒,0 表示永久有效,仅普通键可能有值)*/int ttl() const;/*** @brief 获取键绑定的租约 ID(租约过期时键会被自动删除)* @return 租约 ID(0 表示未绑定租约)*/int64_t lease() const;protected:// 友元类声明:允许这些类直接访问 Value 的内部成员(初始化/赋值用)friend class Client;friend class SyncClient;friend class Response;friend class Event;// 构造函数(仅友元类可调用,外部通过 Response 等间接获取 Value 对象)Value();                                  // 空构造:初始化空键值对Value(etcdv3::KeyValue const & kvs);      // 从 etcd v3 底层键值对象构造Value(mvccpb::KeyValue const & kvs);      // 从 mvccpb 底层键值对象构造// 内部存储的键值信息(外部通过 public 方法访问,不直接暴露)std::string _key;       // 键名(绝对路径)bool        dir;        // 是否为目录(true=目录,false=普通键)std::string value;      // 键值(仅普通键有效)int64_t     created;    // 创建索引int64_t     modified;   // 最后修改索引int64_t     _version;   // 版本号int         _ttl;       // 过期时间(秒)int64_t     leaseId;    // 绑定的租约 ID};// 定义 Values 类型:Value 对象的列表,用于存储多个键值对(如目录下的所有键)typedef std::vector<Value> Values;// =========================================================================// 核心2:etcd::Event 类(监听事件载体)// =========================================================================/*** @brief etcd 监听操作(watch)的事件封装类* 存储键值变更的事件类型(新增/修改/删除)及变更前后的键值数据,仅在 watch 响应中使用*/class Event{public:// 事件类型枚举:明确事件是“新增/修改”还是“删除”enum class EventType {PUT,       // 新增或修改键(键不存在则新增,存在则修改)DELETE_,   // 删除键INVALID    // 无效事件(异常场景下的默认值)};/*** @brief 获取事件类型(判断是新增/修改还是删除)* @return 事件类型(EventType::PUT / EventType::DELETE_ / EventType::INVALID)*/enum EventType event_type() const;/*** @brief 判断事件是否包含“变更后的键值”(PUT 事件有,DELETE 事件无)* @return true = 包含变更后键值;false = 不包含*/bool has_kv() const;/*** @brief 判断事件是否包含“变更前的键值”(修改/删除事件可能有,新增事件无)* @return true = 包含变更前键值;false = 不包含*/bool has_prev_kv() const;/*** @brief 获取“变更后的键值”(仅 has_kv() 为 true 时有效)* @return 变更后的 Value 对象(不可修改)*/const Value &kv() const;/*** @brief 获取“变更前的键值”(仅 has_prev_kv() 为 true 时有效)* @return 变更前的 Value 对象(不可修改)*/const Value &prev_kv() const;protected:// 友元类声明:仅 Response 可创建 Event 对象(watch 响应中生成)friend class Response;// 构造函数(仅友元类可调用,外部通过 Response::events() 间接获取 Event 对象)Event(mvccpb::Event const & event);  // 从 mvccpb 底层事件对象构造private:// 内部存储的事件信息(外部通过 public 方法访问,不直接暴露)enum EventType event_type_;  // 事件类型Value _kv;                   // 变更后的键值(PUT 事件有效)Value _prev_kv;              // 变更前的键值(修改/删除事件可能有效)bool _has_kv;                // 是否包含变更后键值bool _has_prev_kv;           // 是否包含变更前键值};// 定义 Events 类型:Event 对象的列表,用于存储多个监听事件(如一次 watch 触发多个变更)typedef std::vector<Event> Events;
}#endif // __ETCD_VECTOR_CORE_HPP__

etcd::Watcher

1. etcd::Watcher 核心函数与参数表格

函数原型参数解释作用
Watcher(Client const &client, std::string const & key, std::function<void(Response)> callback, bool recursive=false)- client:etcd 客户端实例- key:监听的键- callback:事件触发时的回调函数- recursive:是否递归监听子树(默认 false)基于客户端监听单个键(非递归)
Watcher(SyncClient const &client, std::string const & key, std::function<void(Response)> callback, bool recursive=false)参数同上,客户端为同步类型 SyncClient基于同步客户端监听单个键
Watcher(Client const &client, std::string const & key, std::string const &range_end, std::function<void(Response)> callback)- range_end:监听范围的结束键([key, range_end))监听键范围 [key, range_end)
Watcher(Client const &client, std::string const & key, int64_t fromIndex, std::function<void(Response)> callback, bool recursive=false)- fromIndex:起始版本号(从该版本开始监听)从指定版本开始监听单个键
Watcher(Client const &client, std::string const & key, std::string const &range_end, int64_t fromIndex, std::function<void(Response)> callback)结合键范围和起始版本从指定版本开始监听键范围
其他构造函数包含地址、用户名密码、SSL 证书等参数直接通过连接信息初始化监听器(无需提前创建客户端)
bool Wait()无参数阻塞等待监听器停止(正常取消返回 true,异常停止返回 false)
void Wait(std::function<void(bool)> callback)- callback:监听器停止后的回调(参数为是否正常取消)异步等待监听器停止
bool Cancel()无参数主动停止监听(成功返回 true)
bool Cancelled() const无参数判断监听器是否已停止(返回 true 表示已停止)
~Watcher()无参数析构函数,释放监听资源

2. 精简化参考源代码

#ifndef __ETCD_WATCHER_SIMPLE_HPP__
#define __ETCD_WATCHER_SIMPLE_HPP__#include <atomic>
#include <functional>
#include <string>
#include <thread>
#include <memory>// 引入依赖的核心类
#include "etcd/Response.hpp"
#include "etcd/Client.hpp"
#include "etcd/SyncClient.hpp"namespace etcd
{/*** @brief 键值监听核心类(Watcher)* 持续监听 etcd 中指定键或键范围的变化(新增、修改、删除),* 当变化发生时通过回调函数通知用户,支持同步/异步等待和主动停止。*/class Watcher{public:// =========================================================================// 核心:构造函数(初始化监听配置)// =========================================================================/*** @brief 基于客户端监听单个键(最常用)* @param client 已初始化的 etcd 客户端(Client 类型)* @param key 要监听的键名(如 "/config/db/host")* @param callback 事件触发时的回调函数(参数为 Response,包含事件详情)* @param recursive 是否递归监听子键(true=监听整个子树,false=仅监听当前键,默认 false)*/Watcher(Client const &client, std::string const & key,std::function<void(Response)> callback, bool recursive = false);/*** @brief 基于同步客户端监听单个键* @param client 已初始化的同步客户端(SyncClient 类型)* @param key 要监听的键名* @param callback 事件回调函数* @param recursive 是否递归监听(默认 false)*/Watcher(SyncClient const &client, std::string const & key,std::function<void(Response)> callback, bool recursive = false);/*** @brief 监听键范围 [key, range_end)* @param client 已初始化的 etcd 客户端* @param key 范围起始键* @param range_end 范围结束键(不包含)* @param callback 事件回调函数*/Watcher(Client const &client, std::string const & key,std::string const &range_end,std::function<void(Response)> callback);/*** @brief 从指定版本开始监听单个键* @param client 已初始化的 etcd 客户端* @param key 要监听的键名* @param fromIndex 起始版本号(从该版本后的变化会被监听)* @param callback 事件回调函数* @param recursive 是否递归监听(默认 false)*/Watcher(Client const &client, std::string const & key,int64_t fromIndex,std::function<void(Response)> callback, bool recursive = false);/*** @brief 直接通过地址监听(无需提前创建客户端)* @param address etcd 服务地址(如 "http://127.0.0.1:2379")* @param key 要监听的键名* @param callback 事件回调函数* @param recursive 是否递归监听(默认 false)*/Watcher(std::string const & address, std::string const & key,std::function<void(Response)> callback, bool recursive = false);/*** @brief 带认证的监听(通过用户名密码连接)* @param address etcd 服务地址* @param username 认证用户名* @param password 认证密码* @param key 要监听的键名* @param callback 事件回调函数* @param recursive 是否递归监听(默认 false)*/Watcher(std::string const & address,std::string const & username, std::string const & password,std::string const & key,std::function<void(Response)> callback, bool recursive = false);// 禁用拷贝和移动(监听器不可复制)Watcher(Watcher const &) = delete;Watcher(Watcher &&) = delete;// =========================================================================// 核心:监听控制接口// =========================================================================/*** @brief 阻塞等待监听停止(如主动取消或连接断开)* @return true = 正常取消;false = 异常停止(如网络错误)*/bool Wait();/*** @brief 异步等待监听停止(非阻塞)* @param callback 停止后的回调函数(参数为是否正常取消)*/void Wait(std::function<void(bool)> callback);/*** @brief 主动停止监听* @return true = 成功取消;false = 已停止或取消失败*/bool Cancel();/*** @brief 检查监听是否已停止* @return true = 已停止;false = 正在运行*/bool Cancelled() const;/*** @brief 析构函数:自动停止监听并释放资源*/~Watcher();protected:// 内部实现:执行监听逻辑(初学者无需关注)void doWatch(std::string const & key,std::string const & range_end,std::string const & auth_token,std::function<void(Response)> callback);std::function<void(Response)> callback;       // 事件回调函数std::function<void(bool)> wait_callback;      // 等待结束回调函数std::thread task_;                            // 监听线程(独立线程运行)// 内部存储的 etcd 服务连接信息(自动管理生命周期)struct EtcdServerStubs;struct EtcdServerStubsDeleter {void operator()(EtcdServerStubs *stubs);};std::unique_ptr<EtcdServerStubs, EtcdServerStubsDeleter> stubs;private:int64_t fromIndex{0};               // 起始版本号(0 表示从当前版本开始)bool recursive{false};              // 是否递归监听std::atomic_bool cancelled{false};  // 监听状态(是否已停止)};
}#endif // __ETCD_WATCHER_SIMPLE_HPP__

3. 参考使用

  1. 核心作用Watcher 是 etcd 的 “监听器”,用于实时监控键的变化,当键被新增、修改或删除时,会通过回调函数通知你。

  2. 使用流程

    // 1. 创建客户端
    etcd::Client client("http://127.0.0.1:2379");// 2. 定义事件回调函数(键变化时会自动调用)
    auto callback = [](etcd::Response const& resp) {if (resp.is_ok()) {for (auto const& event : resp.events()) {std::cout << "事件类型: " << (event.event_type() == etcd::Event::EventType::PUT ? "修改/新增" : "删除") << std::endl;std::cout << "键: " << event.kv().key() << std::endl;}}
    };// 3. 创建监听器,监听 "/test" 键(递归监听子键)
    etcd::Watcher watcher(client, "/test", callback, true);// 4. 等待监听(阻塞当前线程,或用异步 Wait)
    watcher.Wait();// 5. 不需要时主动停止(通常在析构时自动调用)
    // watcher.Cancel();
    
  3. 关键接口

    • 构造函数:决定监听 “哪个键”“从哪个版本开始”“是否递归”。
    • Cancel():主动停止监听(必须调用,否则线程可能泄漏)。
    • 回调函数:处理实际的键变化事件(核心业务逻辑在这里实现)。

etcd::KeepAlive

1. etcd::KeepAlive 核心函数与参数表格

函数原型参数解释作用
构造函数系列初始化租约保活器,绑定租约并设置自动续期
KeepAlive(Client const &client, int ttl, int64_t lease_id = 0)- client:etcd 客户端实例- ttl:租约有效期(秒)- lease_id:租约 ID(0 表示自动生成)基于客户端创建租约保活器
KeepAlive(SyncClient const &client, int ttl, int64_t lease_id = 0)参数同上,客户端为同步类型 SyncClient基于同步客户端创建保活器
KeepAlive(std::string const & address, int ttl, int64_t lease_id = 0)- address:etcd 服务地址直接通过地址创建保活器(无需提前创建客户端)
KeepAlive(Client const &client, std::function<void (std::exception_ptr)> const &handler, int ttl, int64_t lease_id = 0)- handler:异常回调函数(保活失败时触发)带异常处理的保活器创建
其他构造函数包含用户名密码、SSL 证书等参数带认证 / 加密的保活器创建
int64_t Lease() const无参数返回当前保活的租约 ID
void Cancel()无参数停止租约保活(租约将在 TTL 后过期)
void Check()无参数检查保活状态(异常时抛出错误)
template <typename Rep = std::micro> void set_grpc_timeout(std::chrono::duration<Rep> const &timeout)- timeout:gRPC 操作超时时间设置保活请求的超时时间
std::chrono::microseconds get_grpc_timeout() const无参数获取当前 gRPC 超时时间
~KeepAlive()无参数析构函数,自动停止保活

2. 精简版 etcd::KeepAlive 头文件(初学者友好)

#ifndef __ETCD_KEEPALIVE_SIMPLE_HPP__
#define __ETCD_KEEPALIVE_SIMPLE_HPP__#include <atomic>
#include <chrono>
#include <exception>
#include <functional>
#include <string>
#include <thread>
#include <memory>// 引入依赖的核心类
#include "etcd/Client.hpp"
#include "etcd/SyncClient.hpp"// Boost Asio 库(用于定时器,处理定时续期)
#include <boost/config.hpp>
#if BOOST_VERSION >= 106600
#include <boost/asio/io_context.hpp>
#else
#include <boost/asio/io_service.hpp>
#endif
#include <boost/asio/steady_timer.hpp>namespace etcd
{/*** @brief 租约保活核心类(KeepAlive)* 自动维护 etcd 租约的有效性,定期向 etcd 发送续期请求,* 确保绑定了该租约的键不会过期删除。*/class KeepAlive{public:// =========================================================================// 核心:构造函数(初始化租约保活配置)// =========================================================================/*** @brief 基于客户端创建租约保活器(最常用)* @param client 已初始化的 etcd 客户端(Client 类型)* @param ttl 租约有效期(秒,保活器会定期续期以维持租约)* @param lease_id 租约 ID(0 表示自动生成新租约,默认 0)*/KeepAlive(Client const &client, int ttl, int64_t lease_id = 0);/*** @brief 基于同步客户端创建租约保活器* @param client 已初始化的同步客户端(SyncClient 类型)* @param ttl 租约有效期(秒)* @param lease_id 租约 ID(0 表示自动生成,默认 0)*/KeepAlive(SyncClient const &client, int ttl, int64_t lease_id = 0);/*** @brief 直接通过地址创建租约保活器(无需提前创建客户端)* @param address etcd 服务地址(如 "http://127.0.0.1:2379")* @param ttl 租约有效期(秒)* @param lease_id 租约 ID(0 表示自动生成,默认 0)*/KeepAlive(std::string const & address, int ttl, int64_t lease_id = 0);/*** @brief 带异常回调的保活器创建* @param client 已初始化的 etcd 客户端* @param handler 异常回调函数(保活失败时触发,参数为异常指针)* @param ttl 租约有效期(秒)* @param lease_id 租约 ID(0 表示自动生成,默认 0)*/KeepAlive(Client const &client,std::function<void (std::exception_ptr)> const &handler,int ttl, int64_t lease_id = 0);/*** @brief 带认证的保活器创建* @param address etcd 服务地址* @param username 认证用户名* @param password 认证密码* @param ttl 租约有效期(秒)* @param lease_id 租约 ID(0 表示自动生成,默认 0)*/KeepAlive(std::string const & address,std::string const & username, std::string const & password,int ttl, int64_t lease_id = 0);// 禁用拷贝和移动(保活器不可复制)KeepAlive(KeepAlive const &) = delete;KeepAlive(KeepAlive &&) = delete;// =========================================================================// 核心:租约保活接口// =========================================================================/*** @brief 获取当前保活的租约 ID* @return 租约 ID(非 0 整数)*/int64_t Lease() const { return lease_id; }/*** @brief 停止租约保活(租约将在 TTL 后自动过期)*/void Cancel();/*** @brief 检查保活状态(异常时抛出错误)* 若保活正常无操作,若发生异常(如网络中断)则重新抛出异常*/void Check();/*** @brief 设置 gRPC 操作超时时间* @tparam Rep 时间单位类型(默认微秒,如 std::chrono::seconds 表示秒)* @param timeout 超时时间(如 std::chrono::seconds(2) 表示 2 秒)*/template <typename Rep = std::micro>void set_grpc_timeout(std::chrono::duration<Rep> const &timeout) {this->grpc_timeout = std::chrono::duration_cast<std::chrono::microseconds>(timeout);}/*** @brief 获取当前 gRPC 超时时间* @return 超时时间(单位:微秒)*/std::chrono::microseconds get_grpc_timeout() const {return this->grpc_timeout;}/*** @brief 析构函数:自动停止保活并释放资源*/~KeepAlive();protected:// 内部实现:定时发送续期请求(初学者无需关注)void refresh();// 内部存储的 etcd 服务连接信息(自动管理生命周期)struct EtcdServerStubs;struct EtcdServerStubsDeleter {void operator()(EtcdServerStubs *stubs);};std::unique_ptr<EtcdServerStubs, EtcdServerStubsDeleter> stubs;private:std::exception_ptr eptr_;                     // 异常存储(用于 Check() 抛出)std::function<void (std::exception_ptr)> handler_; // 异常回调函数std::thread task_;                            // 保活线程(独立线程运行)int ttl;                                      // 租约有效期(秒)int64_t lease_id;                             // 租约 IDstd::atomic_bool continue_next{true};         // 保活状态(是否继续续期)std::chrono::microseconds grpc_timeout{0};    // gRPC 超时时间(微秒)// Boost 定时器(用于定期触发续期)
#if BOOST_VERSION >= 106600boost::asio::io_context context;
#elseboost::asio::io_service context;
#endifstd::unique_ptr<boost::asio::steady_timer> keepalive_timer_;};
}#endif // __ETCD_KEEPALIVE_SIMPLE_HPP__

3. 给初学者的关键说明

  1. 核心作用KeepAlive 是 etcd 租约的 “续命器”。当你为键绑定租约后,需要定期向 etcd 发送续期请求才能维持租约有效,KeepAlive 会自动完成这个过程,避免键被自动删除。

  2. 使用流程

    // 1. 创建客户端
    etcd::Client client("http://127.0.0.1:2379");// 2. 创建租约保活器(TTL=30秒,自动生成租约ID)
    auto keepalive = client.leasekeepalive(30);// 3. 获取租约ID(用于绑定键)
    int64_t lease_id = keepalive->Lease();// 4. 为键绑定租约(键会在租约过期后自动删除)
    client.set("/test/key", "value", lease_id);// 5. 不需要时停止保活(租约将在30秒后过期,键被删除)
    // keepalive->Cancel();
    
  3. 关键接口

    • 构造函数:指定租约有效期(TTL),保活器会每 TTL/3 左右自动续期一次。
    • Lease():获取租约 ID,用于将键绑定到该租约。
    • Cancel():停止续期(必须调用,否则租约会一直有效)。
    • 异常回调:保活失败(如网络中断)时触发,可用于错误处理或重连。

pplx::task

1. 模板类 task<_ReturnType> 核心函数与参数表格

函数原型(简化)核心参数解释作用
构造函数创建异步任务对象,承载异步逻辑或任务状态
task()无参数默认构造(空任务),不可直接使用(需赋值后才能调用 wait()/get()
task(_Ty _Param)_Param:可调用对象(lambda / 函数 / 函数对象),或任务完成事件基于 “异步逻辑” 创建任务(如 lambda 中的耗时操作)
task(_Ty _Param, const task_options& _TaskOptions)_Param:同上;_TaskOptions:任务配置(取消令牌、调度器等)带配置的任务创建(如指定任务取消规则)
task(const task& _Other)_Other:其他 task 对象拷贝构造(任务共享底层状态,类似智能指针)
task(task&& _Other)_Other:其他 task 对象(右值)移动构造(转移底层状态,避免拷贝开销)
赋值运算符替换任务的底层状态
task& operator=(const task& _Other)_Other:其他 task 对象拷贝赋值(共享目标任务状态)
task& operator=(task&& _Other)_Other:其他 task 对象(右值)移动赋值(转移目标任务状态)
任务延续(核心)任务完成后自动执行的后续逻辑(避免回调嵌套)
auto then(_Function&& _Func) const_Func:延续函数(参数为当前任务结果 / 自身,返回值为新任务结果)为当前任务绑定延续任务(如 “任务 A 完成后执行任务 B”)
auto then(_Function&& _Func, task_options _TaskOptions) const_Func:同上;_TaskOptions:延续任务配置带配置的延续任务(如指定延续任务的调度器)
任务等待与结果获取同步获取任务状态或结果
task_status wait() const无参数阻塞等待任务完成(返回 completed/canceled,异常时抛出)
_ReturnType get() const无参数阻塞等待并获取任务结果(任务取消 / 异常时抛出错误)
任务状态查询检查任务是否完成
bool is_done() const无参数判断任务是否进入 “终态”(完成 / 取消 / 异常,返回 true/false
任务调度器相关管理任务的执行调度器
scheduler_ptr scheduler() const无参数获取当前任务使用的调度器(控制任务在哪个线程执行)
任务比较判断两个任务是否指向同一底层状态
bool operator==(const task& _Rhs) const_Rhs:另一个 task 对象相等则表示共享同一底层任务
bool operator!=(const task& _Rhs) const_Rhs:另一个 task 对象
http://www.dtcms.com/a/427311.html

相关文章:

  • [特殊字符]️ Spring Cloud Eureka 三步通:搭建注册中心 + 服务注册 + 服务发现,通俗易懂!
  • 打工人日报#20250930
  • 六安网站建设网络服务中国都在那个网站上做外贸
  • 软件工程实践团队作业——团队组建与实践选题
  • YDWE编辑器系列教程二:物体编辑器
  • 软考-系统架构设计师 NoSQL数据库详细讲解
  • 钢铁厂设备健康监测系统:AIoT技术驱动的智慧运维革命​
  • Elasticsearch集群监控信息(亲测)
  • TARA (威胁分析与风险评估) 学习笔记
  • 网站集成微信登陆如何选择大良网站建设
  • 鸿蒙:使用Image组件展示相册图片或rawfile图片
  • ubuntu系统当前的时间和时区
  • 图解式部署:WSL2 中 Dify 本地化安装与访问故障排查指南
  • ABAP+新值过长,仅可以传输255个元素
  • 顺序队列与环形队列的基本概述及应用
  • 数组的三角和
  • 文创产品设计的目的和意义岳阳优化营商环境
  • Spring Boot 内置日志框架 Logback - 以及 lombok 介绍
  • 网站优化塔山双喜百度关键词快速排名方法
  • 第十二届全国社会媒体处理大会笔记
  • FFmpeg暂停、逐帧和音量
  • QT中的QTimer.singleShot()函数
  • TCP/IP 四层模型协作流程详解
  • windows显示驱动开发-调试间接显示驱动程序(一)
  • MySQL MVCC:通过 ReadView与 undolog版本链 分析读提交RC和可重复读RR的原理
  • STM32-USB_OTG_FS 与 USB_OTG_HS 的核心区别
  • 输入框内容粘贴时 nbsp; 字符净化问题
  • 网站建设要做哪些黑龙江牡丹江双鸭山伊春推广
  • 软考 系统架构设计师系列知识点之杂项集萃(163)
  • matlab cell 数据转换及记录