diff --git a/polaris/quota/model/rate_limit_rule.cpp b/polaris/quota/model/rate_limit_rule.cpp index c468d43..bf034b2 100644 --- a/polaris/quota/model/rate_limit_rule.cpp +++ b/polaris/quota/model/rate_limit_rule.cpp @@ -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), @@ -139,8 +141,8 @@ bool RateLimitRule::InitMatch(const google::protobuf::Map::iterator bucket_it; const std::map& 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::const_iterator it = remote_usage.begin(); it != remote_usage.end(); ++it) { bucket_it = token_buckets_.find(it->first); @@ -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; } } diff --git a/polaris/quota/rate_limit_connector.cpp b/polaris/quota/rate_limit_connector.cpp index cd2a1fa..673fe13 100644 --- a/polaris/quota/rate_limit_connector.cpp +++ b/polaris/quota/rate_limit_connector.cpp @@ -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流程中,删除对应的数据 diff --git a/polaris/quota/rate_limit_window.cpp b/polaris/quota/rate_limit_window.cpp index a6c0174..a59d774 100644 --- a/polaris/quota/rate_limit_window.cpp +++ b/polaris/quota/rate_limit_window.cpp @@ -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() { diff --git a/test/quota/quota_bucket_qps_test.cpp b/test/quota/quota_bucket_qps_test.cpp index 9a79637..1cae4b2 100644 --- a/test/quota/quota_bucket_qps_test.cpp +++ b/test/quota/quota_bucket_qps_test.cpp @@ -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); @@ -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,需加快上报 diff --git a/test/quota/quota_limit_rule_test.cpp b/test/quota/quota_limit_rule_test.cpp index e290c1d..ea14d27 100644 --- a/test/quota/quota_limit_rule_test.cpp +++ b/test/quota/quota_limit_rule_test.cpp @@ -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) {