Skip to content

Commit

Permalink
Merge pull request #10 from lambdaliu/rate_limit
Browse files Browse the repository at this point in the history
feat: add report interval config for limit quota sync
  • Loading branch information
lambdaliu authored Oct 2, 2021
2 parents 019b2d1 + 90268d0 commit 10b2f22
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 10 deletions.
13 changes: 11 additions & 2 deletions polaris/quota/model/rate_limit_rule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ bool RateLimitWindowKey::operator==(const RateLimitWindowKey& rhs) const {
this->regex_labels_ == rhs.regex_labels_;
}

uint32_t RateLimitReport::IntervalWithJitter() const { return interval_ + rand() % jitter_; }

RateLimitRule::RateLimitRule()
: priority_(0), limit_resource_(v1::Rule::QPS), limit_type_(v1::Rule::GLOBAL),
amount_mode_(v1::Rule::GLOBAL_TOTAL), action_type_(kRateLimitActionReject), disable_(true),
Expand Down Expand Up @@ -139,8 +141,8 @@ bool RateLimitRule::InitMatch(const google::protobuf::Map<std::string, v1::Match
}

bool RateLimitRule::InitReportConfig(const v1::Rule& rule) {
static const uint64_t kDefaultLimitReportInterval = 100; // 默认上报间隔
static const uint64_t kMinRateLimitReportInterval = 20; // 最小限流上报周期
static const uint64_t kDefaultLimitReportInterval = 40; // 默认上报间隔
static const uint64_t kMinRateLimitReportInterval = 2; // 最小限流上报周期
static const uint64_t kMaxRateLimitReportInterval = 5 * 1000; // 最大限流上报周期
static const uint64_t kRateLimitReportAmountPresent = 80; // 默认满足百分之80的请求后立刻限流上报
static const uint64_t kMaxRateLimitReportAmountPresent = 100; // 最大实时上报百分比
Expand All @@ -166,6 +168,13 @@ bool RateLimitRule::InitReportConfig(const v1::Rule& rule) {
} else {
report_.interval_ = kDefaultLimitReportInterval;
}

// 设置 jitter
report_.jitter_ = report_.interval_ * 4 / 10;
if (report_.jitter_ < 1) {
report_.jitter_ = 1;
}
report_.interval_ = report_.interval_ - report_.jitter_ / 2;
return true;
}

Expand Down
5 changes: 4 additions & 1 deletion polaris/quota/model/rate_limit_rule.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ struct RateLimitAmount {

// 限流上报配置
struct RateLimitReport {
RateLimitReport() : interval_(0), amount_percent_(0) {}
RateLimitReport() : interval_(0), jitter_(0), amount_percent_(0) {}
uint32_t interval_; // 配额固定上报周期,单位ms
uint32_t jitter_; // 上报周期抖动范围
uint32_t amount_percent_; // 配额使用达到百分比上报,值范围(0, 100]

uint32_t IntervalWithJitter() const;
};

// 限流动作类型
Expand Down
6 changes: 3 additions & 3 deletions polaris/quota/quota_bucket_qps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ uint64_t TokenBucket::RefreshToken(int64_t remote_left, int64_t ack_quota,
uint64_t current_time) {
int64_t last_token_remote_total = remote_quota_.remote_token_total_;
remote_quota_.remote_token_total_ = remote_left;
uint64_t next_report_time = 0;
uint64_t next_report_time = Time::kMaxTime;
if (remote_quota_expired) { // 初始化或配额已经过期
int64_t remote_token_left = remote_quota_.remote_token_left_;
int64_t remote_token_total = remote_quota_.remote_token_total_;
Expand Down Expand Up @@ -246,7 +246,7 @@ uint64_t RemoteAwareQpsBucket::SetRemoteQuota(const RemoteQuotaResult& remote_qu
std::map<uint64_t, TokenBucket>::iterator bucket_it;
const std::map<uint64_t, QuotaUsage>& remote_usage =
remote_quota_result.remote_usage_.quota_usage_;
uint64_t next_report_time = 0;
uint64_t next_report_time = Time::kMaxTime;
for (std::map<uint64_t, QuotaUsage>::const_iterator it = remote_usage.begin();
it != remote_usage.end(); ++it) {
bucket_it = token_buckets_.find(it->first);
Expand All @@ -268,7 +268,7 @@ uint64_t RemoteAwareQpsBucket::SetRemoteQuota(const RemoteQuotaResult& remote_qu
uint64_t report_time = bucket.RefreshToken(remote_quota, local_used, current_bucket_time,
current_time >= last_remote_sync_time_ + it->first,
current_time % it->first);
if (report_time > 0 && (report_time < next_report_time || next_report_time == 0)) {
if (report_time < next_report_time) {
next_report_time = report_time;
}
}
Expand Down
4 changes: 3 additions & 1 deletion polaris/quota/rate_limit_connector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,9 @@ void RateLimitConnection::OnInitResponse(const metric::v2::RateLimitInitResponse
window->OnInitResponse(response, time_diff_);

connector_.UpdateCallResult(cluster_, instance_id_, delay, kServerCodeReturnOk);
reactor_.AddTimingTask(new WindowSyncTask(window, &connector_, 30 + rand() % 20));
reactor_.AddTimingTask(new WindowSyncTask(
window, &connector_,
window->GetRateLimitRule()->GetRateLimitReport().IntervalWithJitter()));
return;
}
limit_target_map_.erase(target_key); // 窗口已经不再init流程中,删除对应的数据
Expand Down
3 changes: 2 additions & 1 deletion polaris/quota/rate_limit_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ uint64_t RateLimitWindow::OnReportResponse(const metric::v2::RateLimitReportResp
delete usage_info_;
usage_info_ = NULL;
}
return next_report_time != 0 ? next_report_time : (30 + rand() % 20);
uint32_t report_interval = rule_->GetRateLimitReport().IntervalWithJitter();
return next_report_time < report_interval ? next_report_time : report_interval;
}

bool RateLimitWindow::IsExpired() {
Expand Down
4 changes: 2 additions & 2 deletions test/quota/quota_bucket_qps_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ TEST_F(TokenBucketTest, RefreshTokenWithLeft) {
uint64_t expect_bucket_time = current_time / 1000;
// 还剩10次,不需要加快上报
uint64_t report_time = token_bucket_.RefreshToken(10, 0, expect_bucket_time, false, 0);
ASSERT_EQ(report_time, 0);
ASSERT_EQ(report_time, Time::kMaxTime);
for (int i = 0; i < 20; ++i) {
int64_t left_quota;
bool result = token_bucket_.GetToken(acquire_amount_, expect_bucket_time, true, left_quota);
Expand All @@ -122,7 +122,7 @@ TEST_F(TokenBucketTest, RefreshTokenWithLeft) {
// 远端还剩6次,本地已上报2次,本地共使用3次,还剩5次
// 80ms消耗5次,剩余需要80ms,还无需加快上报
report_time = token_bucket_.RefreshToken(6, 2, expect_bucket_time, false, 80);
ASSERT_EQ(report_time, 0);
ASSERT_EQ(report_time, Time::kMaxTime);
}
if (i == 3) {
// 远端还剩4次,本地又上报1次,共使用4次,100ms消耗7次,需要42ms,需加快上报
Expand Down
7 changes: 7 additions & 0 deletions test/quota/quota_limit_rule_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ TEST(RateLimitRuleTest, InitReport) {

rule.mutable_report()->mutable_amountpercent()->set_value(50);
ASSERT_TRUE(rate_limit_rule.Init(rule));

rule.mutable_report()->mutable_interval()->set_nanos(50 * 1000 * 1000);
ASSERT_TRUE(rate_limit_rule.Init(rule));
ASSERT_EQ(rate_limit_rule.GetRateLimitReport().interval_, 40);
ASSERT_EQ(rate_limit_rule.GetRateLimitReport().jitter_, 20);
ASSERT_GE(rate_limit_rule.GetRateLimitReport().IntervalWithJitter(), 40);
ASSERT_LE(rate_limit_rule.GetRateLimitReport().IntervalWithJitter(), 60);
}

TEST(RateLimitRuleTest, SortByPriority) {
Expand Down

0 comments on commit 10b2f22

Please sign in to comment.