Skip to content

Commit 695b48d

Browse files
committed
slow down select half open instance
1 parent 5f960ea commit 695b48d

File tree

9 files changed

+58
-25
lines changed

9 files changed

+58
-25
lines changed

polaris/engine/circuit_breaker_executor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void CircuitBreakerExecutor::TimingCircuitBreak(CircuitBreakerExecutor* executor
5757
all_service_contexts.clear();
5858
// 设置定时任务
5959
executor->reactor_.AddTimingTask(
60-
new TimingFuncTask<CircuitBreakerExecutor>(TimingCircuitBreak, executor, 500));
60+
new TimingFuncTask<CircuitBreakerExecutor>(TimingCircuitBreak, executor, 1000));
6161
}
6262

6363
} // namespace polaris

polaris/model/model.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,7 @@ void Service::SetCircuitBreakerData(const CircuitBreakerData& circuit_breaker_da
995995
impl_->have_half_open_data_ = true;
996996
} else {
997997
impl_->have_half_open_data_ = false;
998+
impl_->try_half_open_count_ = 20;
998999
}
9991000
}
10001001

@@ -1020,6 +1021,19 @@ ReturnCode Service::TryChooseHalfOpenInstance(std::set<Instance*>& instances, In
10201021
if (!impl_->have_half_open_data_ || instances.empty()) {
10211022
return kReturnInstanceNotFound;
10221023
}
1024+
// 控制释放半开节点的评论,有半开节点以后每20个请求
1025+
// 且距离上次释放半开节点超过2s就释放1个半开请求
1026+
if (++impl_->try_half_open_count_ < 20) {
1027+
return kReturnInstanceNotFound; // 距离上次释放不足20个正常请求
1028+
}
1029+
uint64_t last_half_open_time = impl_->last_half_open_time_.Load();
1030+
uint64_t current_time = Time::GetCurrentTimeMs();
1031+
if (current_time < last_half_open_time + 2000 ||
1032+
!impl_->last_half_open_time_.Cas(last_half_open_time, current_time)) {
1033+
return kReturnInstanceNotFound; // 距离上一次释放半开间隔不足2s
1034+
}
1035+
impl_->try_half_open_count_ = 0;
1036+
10231037
std::set<Instance*>::iterator split_it = instances.begin();
10241038
std::advance(split_it, rand() % instances.size());
10251039
std::set<Instance*>::iterator instance_it;

polaris/model/model_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ class ServiceImpl {
300300

301301
// 半开优先分配数据
302302
sync::Mutex half_open_lock_;
303+
sync::Atomic<uint64_t> last_half_open_time_;
304+
sync::Atomic<int> try_half_open_count_;
303305
bool have_half_open_data_;
304306
std::map<std::string, int> half_open_data_; // 存储半开分配数据
305307

polaris/plugin/circuit_breaker/circuit_breaker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static const char kChainEnableKey[] = "enable";
3535
static const bool kChainEnableDefault = true;
3636

3737
static const char kChainCheckPeriodKey[] = "checkPeriod";
38-
static const uint64_t kChainCheckPeriodDefault = 500;
38+
static const uint64_t kChainCheckPeriodDefault = 1000;
3939

4040
// 用于传入是否开启探测插件
4141
static const char kDetectorDisableKey[] = "detectorDisable";

polaris/plugin/circuit_breaker/error_count.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ ReturnCode ErrorCountCircuitBreaker::TimingCircuitBreak(
140140
error_count_status.error_count = 0;
141141
error_count_status.last_update_time = current_time;
142142
}
143-
} else if (error_count_status.last_update_time + 20 * sleep_window_ <= current_time) {
143+
} else if (error_count_status.last_access_time + 100 * sleep_window_ <= current_time) {
144144
// 兜底:如果访问量一定时间达不到要求,则重新熔断
145145
if (instances_status->TranslateStatus(it->first, kCircuitBreakerHalfOpen,
146146
kCircuitBreakerOpen)) {

polaris/plugin/circuit_breaker/error_count.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525

2626
namespace polaris {
2727

28-
class Config;
29-
class Context;
30-
3128
struct ErrorCountStatus {
3229
CircuitBreakerStatus status;
3330
int error_count;

polaris/plugin/circuit_breaker/error_rate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ ReturnCode ErrorRateCircuitBreaker::TimingCircuitBreak(
175175
error_rate_status.ClearBuckets(metric_num_buckets_);
176176
}
177177
} else if (err_req > request_count_after_half_open_ - success_count_after_half_open_ ||
178-
error_rate_status.last_update_time + 20 * sleep_window_ <= current_time) {
178+
error_rate_status.last_access_time + 100 * sleep_window_ <= current_time) {
179179
// 达到重新熔断条件
180180
if (instances_status->TranslateStatus(it->first, kCircuitBreakerHalfOpen,
181181
kCircuitBreakerOpen)) {

polaris/plugin/circuit_breaker/error_rate.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525

2626
namespace polaris {
2727

28-
class Config;
29-
class Context;
30-
3128
struct ErrorRateBucket {
3229
ErrorRateBucket() : total_count(0), error_count(0), bucket_time(0) {}
3330
int total_count;

test/model/model_test.cpp

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "mock/fake_server_response.h"
2121
#include "model/model_impl.h"
2222
#include "polaris/plugin.h"
23+
#include "test_utils.h"
2324
#include "utils/string_utils.h"
2425

2526
namespace polaris {
@@ -29,9 +30,10 @@ class ModelTest : public ::testing::Test {
2930
void SetUp() {
3031
service_key_.namespace_ = "test_namespace";
3132
service_key_.name_ = "test_service";
33+
TestUtils::SetUpFakeTime();
3234
}
3335

34-
void TearDown() {}
36+
void TearDown() { TestUtils::TearDownFakeTime(); }
3537

3638
protected:
3739
ServiceKey service_key_;
@@ -52,26 +54,39 @@ TEST_F(ModelTest, TryChooseHalfOpenInstance) {
5254
service->SetCircuitBreakerData(circuit_breaker_data);
5355

5456
Instance *instance = NULL;
55-
ASSERT_EQ(service->TryChooseHalfOpenInstance(service_instances, instance), kReturnOk);
56-
ASSERT_TRUE(instance != NULL);
57-
ASSERT_EQ(instance->GetId(), "instance_0");
58-
instance = NULL;
59-
ASSERT_EQ(service->TryChooseHalfOpenInstance(service_instances, instance),
60-
kReturnInstanceNotFound);
61-
ASSERT_TRUE(instance == NULL);
57+
for (int i = 1; i <= 60; i++) {
58+
instance = NULL;
59+
ReturnCode ret = service->TryChooseHalfOpenInstance(service_instances, instance);
60+
if (i == 20) {
61+
ASSERT_EQ(ret, kReturnOk) << i;
62+
ASSERT_TRUE(instance != NULL);
63+
ASSERT_EQ(instance->GetId(), "instance_0");
64+
} else {
65+
ASSERT_EQ(ret, kReturnInstanceNotFound);
66+
ASSERT_TRUE(instance == NULL);
67+
}
68+
TestUtils::FakeNowIncrement(1500);
69+
}
6270

6371
circuit_breaker_data.version = 2;
6472
circuit_breaker_data.half_open_instances["instance_0"] = 1;
6573
circuit_breaker_data.half_open_instances["instance_x"] = 2;
6674
circuit_breaker_data.half_open_instances["instance_1"] = 5;
6775
service->SetCircuitBreakerData(circuit_breaker_data);
68-
for (int i = 0; i < 5; i++) {
76+
for (int i = 1; i <= 100; i++) {
6977
instance = NULL;
70-
ASSERT_EQ(service->TryChooseHalfOpenInstance(service_instances, instance), kReturnOk);
71-
ASSERT_TRUE(instance != NULL);
72-
ASSERT_EQ(instance->GetId(), "instance_1");
78+
TestUtils::FakeNowIncrement(1500);
79+
ReturnCode ret = service->TryChooseHalfOpenInstance(service_instances, instance);
80+
if (i % 20 == 0) {
81+
ASSERT_EQ(ret, kReturnOk) << i;
82+
ASSERT_TRUE(instance != NULL);
83+
ASSERT_EQ(instance->GetId(), "instance_1");
84+
} else {
85+
ASSERT_EQ(ret, kReturnInstanceNotFound);
86+
}
7387
}
7488
instance = NULL;
89+
TestUtils::FakeNowIncrement(10000);
7590
ASSERT_EQ(service->TryChooseHalfOpenInstance(service_instances, instance),
7691
kReturnInstanceNotFound);
7792
ASSERT_TRUE(instance == NULL);
@@ -89,6 +104,8 @@ TEST_F(ModelTest, TryChooseHalfOpenInstanceRand) {
89104
Instance *instance;
90105
CircuitBreakerData circuit_breaker_data;
91106
circuit_breaker_data.version = 1;
107+
service->SetCircuitBreakerData(circuit_breaker_data);
108+
circuit_breaker_data.version = 2;
92109
for (int i = 0; i < 10; i++) {
93110
std::string instance_id = "instance_" + StringUtils::TypeToStr<int>(i);
94111
instance = new Instance(instance_id, "host", 8000, 100);
@@ -98,9 +115,15 @@ TEST_F(ModelTest, TryChooseHalfOpenInstanceRand) {
98115
service->SetCircuitBreakerData(circuit_breaker_data);
99116

100117
std::set<Instance *> select_instance;
101-
for (int i = 0; i < 10; i++) {
102-
ASSERT_EQ(service->TryChooseHalfOpenInstance(instances, instance), kReturnOk);
103-
select_instance.insert(instance);
118+
for (int i = 0; i < 200; i++) {
119+
TestUtils::FakeNowIncrement(50);
120+
ReturnCode ret_code = service->TryChooseHalfOpenInstance(instances, instance);
121+
if (i % 40 == 0) {
122+
ASSERT_EQ(ret_code, kReturnOk) << i;
123+
select_instance.insert(instance);
124+
} else {
125+
ASSERT_EQ(ret_code, kReturnInstanceNotFound) << i;
126+
}
104127
}
105128
ASSERT_GT(select_instance.size(), 1);
106129

0 commit comments

Comments
 (0)