服务注册发现

引入依赖

参考文档:依赖引入

初始化 polaris.yaml

你需要在项目的根路径下创建一个 polaris.yaml 文件用于初始化 polaris-cpp SDK。polaris.yaml配置详细

服务注册

SDK实例构建

当初始化好 polaris.yaml 文件之后,你可以直接使用 include polaris/provider.h, 使用polaris::ProviderApi::CreateWithDefaultFile() 方法进行构造一个 ProviderAPI SDK 实例

#include "polaris/provider.h"

int main(int argc, char** argv) {
    provider_ = std::unique_ptr<polaris::ProviderApi>(polaris::ProviderApi::CreateWithDefaultFile());
}

注册请求体

// 服务实例注册请求
// 用于向指定命令空间的服务注册服务实例。必须拥有服务token才能进行服务实例注册。
// 服务实例注册成功后,其他服务调用服务发现接口能发现该服务实例,可能会立即向该服务实例发送请求。
// @note 所以必须在服务实例启动完成后才去进行服务注册。
class InstanceRegisterRequest : Noncopyable {
 public:
  /// @brief 构造服务实例注册请求对象
  /// @param service_namespace 服务名所属命名空间
  /// @param service_name 服务名
  /// @param service_token 服务名对应的token
  /// @param host 服务实例监听地址
  /// @param port 服务实例监听端口
  InstanceRegisterRequest(const std::string& service_namespace, const std::string& service_name,
                          const std::string& service_token, const std::string& host, int port);
  /// @brief 设置请求超时时间。可选,默认为SDK配置的API超时时间
  void SetTimeout(uint64_t timeout);
  /// @brief 设置服务实例的VPC ID。可选,默认为空
  void SetVpcId(const std::string& vpc_id);
  /// @brief 设置服务实例协议。可选,默认为空
  void SetProtocol(const std::string& protocol);
  /// @brief 设置服务实例权重。可选,默认为100
  void SetWeight(int weight);
  /// @brief 设置服务实例优先级。可选,置默认为0
  void SetPriority(int priority);
  /// @brief 设置服务实例版本信息。可选,默认为空
  void SetVersion(const std::string& version);
  /// @brief 设置服务实例的metada数据。可选,默认为空
  void SetMetadata(const std::map<std::string, std::string>& metadata);
  /// @brief 设置服务实例是否开启健康检查。可选,默认不开启
  void SetHealthCheckFlag(bool health_check_flag);
  /// @brief 设置健康检查类型。可选,默认为心跳健康检查
  void SetHealthCheckType(HealthCheckType health_check_type);
  /// @brief 设置心跳健康检查ttl,单位为s,不填默认为5s,
  /// 开启了心跳健康检查,客户端必须以TTL间隔上报心跳
  /// 健康检查服务器3个TTL未受到心跳则将实例置为不健康
  void SetTtl(int ttl);
  /// @brief 设置节点的位置信息。可选
  /// @param region 节点所在区域
  /// @param zone 节点所在城市
  /// @param campus 节点所在园区
  void SetLocation(const std::string& region, const std::string& zone, const std::string& campus);
};

发起注册请求

你在初始化完 InstanceRegisterRequest 结构体后,需要调用 ProviderAPI.Register 方法完成实例注册, 如果实例开启了心跳上报,则还需要调用 heartbeat 方法定期上报实例心跳

polaris::InstanceRegisterRequest register_req(service_namespace_, service_name_, service_token_, host_, port_);
// 开启健康检查
register_req.SetHealthCheckFlag(true);
register_req.SetHealthCheckType(polaris::kHeartbeatHealthCheck);
register_req.SetTtl(kHeartbeatTtl);

// 注册实例
auto ret_code = provider_->Register(register_req, instance_id_);
if (ret_code != polaris::kReturnOk && ret_code != polaris::kReturnExistedResource) {
  std::cout << "register instance with error:" << polaris::ReturnCodeToMsg(ret_code).c_str() << std::endl;
  return ret_code;
}

// 启动心跳上报线程
heartbeat_thread_ = std::unique_ptr<std::thread>(new std::thread([=] {
  while (!signal_received) {  // 循环上报心跳
    polaris::InstanceHeartbeatRequest heartbeat_req(service_token_, instance_id_);
    auto ret_code = provider_->Heartbeat(heartbeat_req);
    if (ret_code != polaris::kReturnOk) {
      std::cout << "instance heartbeat with error:" << polaris::ReturnCodeToMsg(ret_code).c_str() << std::endl;
      sleep(1);
      continue;
    }
    sleep(kHeartbeatTtl);
  }
}));

服务发现

SDK实例构建

当初始化好 polaris.yaml 文件之后,你可以直接使用 include polaris/consumer.h, 使用polaris::ConsumerApi::CreateWithDefaultFile() 方法进行构造一个 ConsumerApi SDK 实例

#include "polaris/consumer.h"

int main(int argc, char** argv) {
    consumer_ = std::unique_ptr<polaris::ConsumerApi>(polaris::ConsumerApi::CreateWithDefaultFile());
}

发现服务实例

GetAllInstances

直接返回目标服务下的所有实例,包括不健康、隔离、权重为0、被熔断的实例,也会在返回的实例列表中。

/// @brief 获取批量服务实例请求
class GetInstancesRequest : Noncopyable {
 public:
  /// @brief 构造获取批量服务实例请求
  /// @param service_key 命名空间和服务名
  explicit GetInstancesRequest(const ServiceKey& service_key);
};

// 调用该方法执行请求
consumer.GetAllInstances()

GetInstances

每次获取一批可用服务提供者实例,该方法会执行路由流程。

该方法默认会过滤掉不健康、隔离、权重为0、被熔断的实例。

/// @brief 获取批量服务实例请求
class GetInstancesRequest : Noncopyable {
 public:
  /// @brief 构造获取批量服务实例请求
  /// @param service_key 命名空间和服务名
  explicit GetInstancesRequest(const ServiceKey& service_key);
  /// @brief 设置服务路由时否包含不健康的服务实例。可选,默认不包含
  /// @note 即使设置不包含的情况下仍然可能降级返回不健康实例
  void SetIncludeUnhealthyInstances(bool include_unhealthy_instances);
  /// @brief 设置服务路由时是否包含熔断的服务实例。可选,默认不包含。
  /// @note 即使设置不包含的情况下仍然可能降级返回熔断实例
  void SetIncludeCircuitBreakInstances(bool include_circuit_breaker_instances);
  /// @brief 设置是否跳过服务路由。可选,默认不跳过服务路由
  void SetSkipRouteFilter(bool skip_route_filter);
  /// @brief 设置源服务信息,用于服务路由计算。可选
  void SetSourceService(const ServiceInfo& source_service);
  /// @brief 设置元数据,用于元数据路由
  void SetMetadata(std::map<std::string, std::string>& metadata);
  /// @brief 设置元数据路由匹配失败时的降级策略,默认不降级
  void SetMetadataFailover(MetadataFailoverType metadata_failover_type);
};

// 调用该方法执行请求
consumer.GetInstances()

GetOneInstances

每次仅获取一个可用服务提供者实例,该方法会依次执行路由、负载均衡流程。

该方法默认会过滤掉不健康、隔离、权重为0、被熔断的实例。

/// @brief 获取单个服务实例请求
class GetOneInstanceRequest : Noncopyable {
 public:
  /// @brief 构建获取单个服务实例请求对象
  /// @param service_key 命名空间和服务名
  explicit GetOneInstanceRequest(const ServiceKey& service_key);
  /// @brief 设置hash key,用于一致性哈希负载均衡算法选择服务实例。其他负载均衡算法不用设置
  void SetHashKey(uint64_t hash_key);
  /// @brief 设置 hash 字符串, sdk 会用 hash_string 算出一个 uint64_t
  /// 的哈希值用于一致性哈希负载均衡算法选择服务实例。其他负载均衡算法不用设置
  void SetHashString(const std::string& hash_string);
  /// @brief 设置是否略过跳过半开探测节点
  /// @note 只在重试业务时设置为true。如果一直设置为true,则熔断节点在网络探测成功后也一直无法恢复
  void SetIgnoreHalfOpen(bool ignore_half_open);
  /// @brief 设置源服务信息,用于服务路由计算。可选
  /// @param source_service 源服务信息,包括源服务命名空间和用于过滤的metadata
  void SetSourceService(const ServiceInfo& source_service);
  /// @brief 设置请求超时时间。可选,默认为全局配置的API超时时间
  void SetTimeout(uint64_t timeout);
  /// @brief 设置请求标签,用于接口级别熔断
  void SetLabels(const std::map<std::string, std::string>& labels);
  /// @brief 设置元数据,用于元数据路由
  void SetMetadata(std::map<std::string, std::string>& metadata);
  /// @brief 设置元数据路由匹配失败时的降级策略,默认不降级
  void SetMetadataFailover(MetadataFailoverType metadata_failover_type);
  /// @brief 设置负载均衡类型。可选,默认使用配置文件中设置的类型
  void SetLoadBalanceType(LoadBalanceType load_balance_type);
  /// @brief 设置用于重试的实例数。可选,默认不返回用于重试的实例
  /// @note 第一个实例由负载均衡器给出,外加backup_instance_num个实例,实例不重复,但不保证数量
  ///       内部的一致性环hash负载均衡返回实例后方相邻的实例,其他返回随机实例
  ///       从GetOneInstance的InstancesResponse获取实例
  /// @param backup_instance_num 重试(备份)实例数
  void SetBackupInstanceNum(uint32_t backup_instance_num);
  /// @param replicate_index 副本索引,默认为0表示当前hash实例本身
  ///                        大于0表示从hash实例后面的第几个副本
  void SetReplicateIndex(int replicate_index);
};

// 调用该方法执行请求
consumer->GetOneInstance(request, instance)

如何基于 polaris-cpp 客户端完成一个服务发现的程序