1 - 使用 C++ SDK
1.1 - 引入依赖
本文档提供如果编译并在自己的项目中引入Polaris CPP SDK方法
编译安装
下载源码
支持两种方式下载源码:
- 使用git clone源码然后切到最新的tag
- 直接在polaris cpp仓库的tags页面上下载最新的tag源码
编译打包
注:目前支持make, bazel方式编译。其他编译方式待支持,欢迎贡献。
make方式编译
# 编译
make
# 测试
make test
# 打包,可添加参数package_name指定打包名,默认polaris_cpp_sdk
make package # package_name=polaris_cpp_sdk
执行make package
后会在当前目录下生成一个polaris_cpp_sdk.tar.gz
压缩文件。该文件的内容如下:
|-- include/polaris # 头文件
| |-- consumer.h provider.h limit.h config.h context.h log.h defs.h ...
|-- dlib # 动态库
| |-- libpolaris_api.so
`-- slib # 静态库
|-- libpolaris_api.a libprotobuf.a
其中include/polaris/
为头文件目录。业务程序使用#include "polaris/xxx.h"
这种方式包含头文件。
dlib/
为动态库目录。libpolaris_api.so
为polaris的动态库。注:该动态库已经链接了libprotobuf.a
使用动态库,在发布应用程序时需要将该动态库一起发布,并需要确保能搜到这些动态库。
slib/
为静态库目录。用户使用静态编译时需要链接该目录下libpolaris_api.a和libprotobuf.a两个静态库。
自定义PB3版本
目前SDK与北极星Server通信使用的PB3,如果用户使用了PB2,需要升级到PB3,PB3兼容PB2。 且当前为了支持c++98编译,默认集成了protobuf 3.5.1版本。用户可以根据需要使用自己的PB3库
在Makefile中找到protobuf相关路径定义,修改以下三个路径指向自己的PB3即可:
PROTOBUF_INC_DIR = # 修改成自己的PB3头文件路径
PROTOBUF_LIB = # 修改成自己的PB3静态库路径
PROTOC = # 修改成自己的PB3可执行文件protoc路径
兼容其他版本PB
有一些业务使用了其他的PB版本,例如PB2或者与北极星自带的PB3.5.1不同的版本。 如果同时链接两个版本的PB库,会导致符号冲突。 有一种方案可以隐藏北极星使用的PB库符号。该方案只支持业务链接北极星动态库时可用。
具体步骤如下:
-
到北极星源码根目录下执行
rm -rf third_party/protobuf/build*
删除编译出来的protobuf库 -
修改北极星Makefile文件,protobuf的configure命令加上符号隐藏选项"CXXFLAGS=-fvisibility=hidden"。 如下是编译64位库时修改的地方:
$(PROTOBUF_DIR)/build64/libprotobuf.a: $(PROTOBUF_DIR)/configure
@echo "[PROTOBUF] Preparing protobuf 64bit lib and protoc"
@cd $(PROTOBUF_DIR); ./configure --with-pic --disable-shared --enable-static "CXXFLAGS=-fvisibility=hidden"
注:编译32位时修改32位PB编译命令的"CXXFLAGS=-m32"
为"CXXFLAGS=-m32 -fvisibility=hidden"
即可
- 在北极星根目录执行make clean 然后重新make即可
bazel方式编译
sh bazel_build.sh # 编译polaris_api
sh bazel_clean.sh # 编译清理
待补充:
test用例的bazel编译待补充
通过Makefile引入
静态库方式使用
g++ -I./polaris_cpp_sdk/include main.cpp -L./polaris_cpp_sdk/slib -lpolaris_api -lprotobuf -pthread -lz -lrt -o main
动态库方式使用
g++ -I./polaris_cpp_sdk/include main.cpp -L./polaris_cpp_sdk/dlib -lpolaris_api -pthread -lz -lrt -o main
通过CMake引入
静态库方式使用
set(POLARIS_SDK_DIR /data/example/polaris_cpp_sdk) # 需要修改polaris_cpp_sdk解压目录
include_directories(${POLARIS_SDK_DIR}/include)
link_directories(${POLARIS_SDK_DIR}/slib)
add_executable(main main.cpp)
target_link_libraries(main libpolaris_api.a libprotobuf.a pthread z rt)
动态库方式使用
set(POLARIS_SDK_DIR /data/example/polaris_cpp_sdk) # 需要修改polaris_cpp_sdk解压目录
include_directories(${POLARIS_SDK_DIR}/include)
link_directories(${POLARIS_SDK_DIR}/dlib)
add_executable(main main.cpp)
target_link_libraries(main polaris_api pthread z rt)
通过Bazel引入
在WORKSPACE中添加依赖:
git_repository(
name = "polaris_cpp",
remote = "https://github.com/polarismesh/polaris-cpp",
tag = "v1.1.0", # 替换成需要依赖的版本
)
在WORKSPACE中加载北极星依赖:
# 可以放到比较后面,这样如果有自定义其他依赖版本,则会优先使用其他自定义版本
load("//:polaris_deps.bzl", "polaris_deps")
polaris_deps()
在BUILD中设置编译目标添加依赖:
deps = [
"@polaris_cpp//:polaris_api",
],
1.2 - 注册发现
引入依赖
参考文档:依赖引入
初始化 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的取值范围为 (0s, 60s]
/// 开启了心跳健康检查,客户端必须以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、被熔断的实例。
执行路由流程的条件
- 配置了 GetInstancesRequest.SourceService.Metadata 属性,会触发自定义路由流程
- 设置了 GetInstancesRequest.Metadata 属性,会触发元数据路由流程
/// @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、被熔断的实例。
执行路由流程的条件
- 配置了 GetOneInstanceRequest.SourceService.Metadata 属性,会触发自定义路由流程
- 设置了 GetOneInstanceRequest.Metadata 属性,会触发元数据路由流程
/// @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 客户端完成一个服务发现的程序
1.3 - 动态路由
引入依赖
参考文档:依赖引入
初始化 polaris.yaml
你需要在项目的根路径下创建一个 polaris.yaml 文件用于初始化 polaris-cpp SDK。polaris.yaml配置详细
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());
}
服务路由
GetInstances
每次获取一批可用服务提供者实例,该方法会执行路由流程。
该方法默认会过滤掉不健康、隔离、权重为0、被熔断的实例。
执行路由流程的条件
- 配置了 GetInstancesRequest.SourceService.Metadata 属性,会触发自定义路由流程
- 设置了 GetInstancesRequest.Metadata 属性,会触发元数据路由流程
/// @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(request, instance)
如果当前 GetInstancesRequest 还不支持 AddArgument 方法,同时服务端版本 >= 1.12.0,SourceService.Metadata 对应的 key 名称如下:
- 路径: $path
- 方法: $method
- 请求头: $header.{标签键}
- 请求参数: $query.{标签键}
- 请求COOKIE: $cookie.{标签键}
- 主调IP: $caller_ip
- 自定义: {标签键}
如何基于 polaris-cpp 客户端完成一个服务路由的程序
1.4 - 负载均衡
引入依赖
参考文档:依赖引入
初始化 polaris.yaml
你需要在项目的根路径下创建一个 polaris.yaml 文件用于初始化 polaris-cpp SDK。polaris.yaml配置详细
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());
}
服务路由
GetInstances
每次获取一批可用服务提供者实例,该方法会执行路由流程。
该方法默认会过滤掉不健康、隔离、权重为0、被熔断的实例。
执行路由流程的条件
- 配置了 GetInstancesRequest.SourceService.Metadata 属性,会触发自定义路由流程
- 设置了 GetInstancesRequest.Metadata 属性,会触发元数据路由流程
/// @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 设置负载均衡类型。可选,默认使用配置文件中设置的类型
/// LoadBalanceType可取值如下:
/// - kLoadBalanceTypeWeightedRandom // 权重随机
/// - kLoadBalanceTypeRingHash // 一致性hash负载均衡
/// - kLoadBalanceTypeMaglevHash // 一致性Hash: maglev算法
/// - kLoadBalanceTypeL5CstHash // 兼容L5的一致性Hash
/// - kLoadBalanceTypeSimpleHash // hash_key%总实例数 选择服务实例
/// - kLoadBalanceTypeDefaultConfig // 使用全局配置的负载均衡算法,默认值
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 客户端完成一个负载均衡的程序
1.5 - 节点熔断
引入依赖
参考文档:依赖引入
初始化 polaris.yaml
你需要在项目的根路径下创建一个 polaris.yaml 文件用于初始化 polaris-go SDK。polaris.yaml配置详细
SDK实例构建
当初始化好 polaris.yaml 文件之后,你可以直接使用 include polaris/consumer.h, 使用polaris::ProviderApi::CreateWithDefaultFile() 方法进行构造一个 ProviderAPI SDK 实例
#include "polaris/consumer.h"
int main(int argc, char** argv) {
consumer_ = std::unique_ptr<polaris::ConsumerApi>(polaris::ConsumerApi::CreateWithDefaultFile());
}
上报调用情况
/// @brief 服务实例调用结果上报
class ServiceCallResult : Noncopyable {
public:
/// @brief 设置服务实例的服务名
void SetServiceName(const std::string& service_name);
/// @brief 设置服务实例的命名空间
void SetServiceNamespace(const std::string& service_namespace);
/// @brief 设置服务实例ID
void SetInstanceId(const std::string& instance_id);
/// @brief 设置服务实例Host和Port,可选,如果设置了服务实例ID,则这个可不设置,优先使用服务实例ID
/// @param host 服务实例Host
/// @param port 服务实例Port
void SetInstanceHostAndPort(const std::string& host, int port);
/// @brief 设置调用返回状态码
void SetRetStatus(CallRetStatus ret_status);
/// @brief 设置调用返回码。可选,用于支持根据返回码实现自己的插件
void SetRetCode(int ret_code);
/// @brief 设置服务实例调用时延
void SetDelay(uint64_t delay);
/// @brief 设置主调服务ServiceKey
void SetSource(const ServiceKey& source);
/// @brief 设置被调服务labels信息
void SetLabels(const std::map<std::string, std::string>& labels);
};
上报请求调用结果
你在根据请求调用情况对 ServiceCallResult 结构体完成初始化后,只需要调用 ConsumerAPI.UpdateServiceCallResult 方法即可完成请求调用结果上报。SDK 内部会根据上报的调用结果信息,对实例进行信息统计并计算是否需要对实例进行熔断
consumer_->UpdateServiceCallResult(result)
如何基于 polaris-go 客户端完成一个节点熔断的程序
1.6 - 访问限流
引入依赖
参考文档:依赖引入
初始化 polaris.yaml
你需要在项目的根路径下创建一个 polaris.yaml 文件用于初始化 polaris-cpp SDK。polaris.yaml配置详细
SDK实例构建
当初始化好 polaris.yaml 文件之后,你可以直接使用 include polaris/limit.h, 使用polaris::LimitApi::CreateWithDefaultFile() 方法进行构造一个 LimitApi SDK 实例
#include "polaris/limit.h"
int main(int argc, char** argv) {
polaris::LimitApi* limit_api = polaris::LimitApi::CreateWithDefaultFile();
}
请求配额
/// @brief 限流配额请求
class QuotaRequest {
public:
/// @brief 设置服务命名空间
void SetServiceNamespace(const std::string& service_namespace);
/// @brief 设置服务名
void SetServiceName(const std::string& service_name);
/// @brief 设置标签用于选择限流配置
void SetLabels(const std::map<std::string, std::string>& labels);
/// @brief 设置请求需要分配的配额数量,可选,默认为1
void SetAcquireAmount(int amount);
/// @brief 设置请求超时时间,可选,单位ms,默认1000ms
void SetTimeout(uint64_t timeout);
/// @brief 设置请求所属的接口名,可选
void SetMethod(const std::string& method);
};
如果当前 QuotaRequest 还不支持 AddArgument 方法,同时服务端版本 >= 1.11.0,SetLabels 对应的 key 名称如下:
- 路径: $path
- 方法: $method
- 请求头: $header.{标签键}
- 请求参数: $query.{标签键}
- 主调服务: $caller_service
- 主调IP: $caller_ip
- 自定义: {标签键}
发起请求配额申请
你在接收到请求之后对 QuotaRequest 结构体完成初始化后,只需要调用 LimitAPI.GetQuota 方法即可完成本次请求配额的申请。
ret = limit_api->GetQuota(quota_request, response)
对于请求配额结果的结构体如下。
/// @brief 配额获取结果
enum QuotaResultCode {
kQuotaResultOk = 0, // 配额正常
kQuotaResultLimited, // 配额被限流
kQuotaResultWait // 需求需要等待重试
};
/// @brief 配额分配信息,sidecar模式下暂时不支持获取这些信息
struct QuotaResultInfo {
int64_t left_quota_; // 剩余配额
int64_t all_quota_; // 配置的配额
uint64_t duration_; // 配置周期
bool is_degrade_; // 是否降级
};
/// @brief 限流配额应答
class QuotaResponse {
public:
/// @brief 获取限流配额结果
QuotaResultCode GetResultCode() const;
/// @brief 获取配额分配信息
const QuotaResultInfo& GetQuotaResultInfo() const;
/// @brief 请求需要获取多长时间才能使用配额
uint64_t GetWaitTime() const;
};
分布式限流使用
如果要使用分布式限流,请先确保已经部署了北极星分布式限流 server
部署完后确认北极星控制台存在服务 命名空间: Polaris, 服务名: polaris.limiter。
确认完毕后,调整 polaris.yaml 配置文件,在控制台配置分布式限流规则,SDK 仍然使用 ret = limit_api->GetQuota(quota_request, response) 即可。
# 描述:限流相关配置
rateLimiter:
# 分布式限流时用于发现限流服务器,当规则中未配置限流集群时使用该配置
rateLimitCluster:
# 限流服务器集群所在命名空间
namespace: Polaris
# 限流服务器集群名字
service: polaris.limiter
如何基于 polaris-cpp 客户端完成一个服务限流的程序
1.7 - 二次寻址
引入依赖
参考文档:依赖引入
初始化 polaris.yaml
你需要在项目的根路径下创建一个 polaris.yaml 文件用于初始化 polaris-cpp SDK。polaris.yaml配置详细
修改 polaris.yaml 开启二次寻址
global:
#描述系统相关配置
system:
# 服务发现集群,用于二次寻址,非二次寻址场景无需配置
discoverCluster:
namespace: Polaris
service: polaris.discover
# 可选:服务刷新间隔
refreshInterval: 10m
# 健康检查集群,用于二次寻址,非二次寻址场景无需配置
healthCheckCluster:
namespace: Polaris
service: polaris.healthcheck
# 可选:服务刷新间隔
refreshInterval: 10m
2 - 使用 L5Agent
环境准备
部署polaris
如果已经部署好了polaris,可忽略这一步。
polaris支持在kubernetes环境中进行部署,注意必须保证暴露HTTP端口为8090,gRPC端口为8091。具体部署方案请参考:
开启服务端的 L5 接入能力
编辑 polaris-server.yaml 配置文件
# apiserver配置
apiservers:
...
# - name: service-l5
# option:
# listenIP: 0.0.0.0
# listenPort: 7779
# clusterName: cl5.discover
将相关注释移除
# apiserver配置
apiservers:
...
- name: service-l5
option:
listenIP: 0.0.0.0
listenPort: 7779
clusterName: cl5.discover
重启 polaris-server
bash tool/stop.sh
bash tool/start.sh
bash tool/stop.cmd
bash tool/start.cmd
修改 L5Agent 配置
修改 L5Agent 安装目录下的 conf/l5_config.ini
配置文件
[L5CONFIG]
ServerIp={北极星服务端IP}
ServerPort=7779
修改完上述配置之后,重启 L5Agent。在重启前需要删除 /data/L5Backup/l5server_list.backup
验证
SID 规范以及注意
- L5 SDI 的格式:ModID:CmdID
- 强烈建议用户命名空间选择 default 或者 Production,ModID 取值范围为: [2, 192,000,000]
- 如果用户确实有需要使用其他命名空间,请按照以下方式进行其他命名空间的换算:ModID 数值右移6位,如果结果 >= 3000001,则需要计算 ModID & 63 的结果值,根据结果值对应的命名空间信息如下,否则会出现L5寻址失败的问题:
{ 1: "Production", 2: "Development", 3: "Pre-release", 4: "Test", 5: "Polaris", 6: "default", }
创建测试服务以及SID
由于 l5api 仅支持访问 L5 SID,因此访问非 L5 SID 格式的服务名,需要创建 CL5 SID 格式的服务别名指向该服务
执行
➜ bin ./L5GetRoute1 192002625 487373 3
ip is :127.0.0.1 port is : 8091, usec=153,avg_usec=153=========================
ip is :127.0.0.1 port is : 8091, usec=2,avg_usec=77=========================
ip is :127.0.0.1 port is : 8091, usec=111,avg_usec=88=========================