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

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;           // 集群ID
                                      uint64_t            _member_id;            // 成员ID
                                      uint64_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;                             // 租约 ID
                                  std::atomic_bool continue_next{true};         // 保活状态(是否继续续期)
                                  std::chrono::microseconds grpc_timeout{0};    // gRPC 超时时间(微秒)
                                  // Boost 定时器(用于定期触发续期)
                                  #if BOOST_VERSION >= 106600
                                  boost::asio::io_context context;
                                  #else
                                  boost::asio::io_service context;
                                  #endif
                                  std::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 对象

posted on 2025-10-16 21:42  slgkaifa  阅读(16)  评论(0)    收藏  举报

导航