Skip to content

Commit 36871db

Browse files
authored
Support origin limit (#48)
* Refactor entry and exit interface * Support tag limit in flow rule * Sharp select strategy of statistics node in flow rule controller * Fix reference problem by incorrect use of auto * Refactor some code in tag flow control module
1 parent f2a9e21 commit 36871db

37 files changed

+246
-188
lines changed

sentinel-core/circuitbreaker/rule_manager.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ CircuitBreakerMap RulePropertyListener::BuildCircuitBreakerMap(
165165
if (it == m.end()) {
166166
m.insert({rule.resource(), {cb}});
167167
} else {
168-
auto vec = it->second;
168+
auto& vec = it->second;
169169
vec.push_back(std::move(cb));
170170
}
171171
}

sentinel-core/circuitbreaker/slot.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "sentinel-core/circuitbreaker/slot.h"
2+
23
#include "sentinel-core/circuitbreaker/rule_manager.h"
34
#include "sentinel-core/utils/time_utils.h"
45

@@ -8,10 +9,10 @@ namespace CircuitBreaker {
89
// CheckerSlot
910

1011
Sentinel::Slot::TokenResultSharedPtr CheckerSlot::Entry(
11-
const EntrySharedPtr& entry, const ResourceWrapperSharedPtr& resource,
12-
Stat::NodeSharedPtr& node, int count, int flag,
12+
const EntrySharedPtr& entry, Stat::NodeSharedPtr& node, int count, int flag,
1313
const std::vector<absl::any>& params) {
14-
auto cbs = RuleManager::GetInstance().GetCircuitBreakers(resource->name());
14+
auto cbs =
15+
RuleManager::GetInstance().GetCircuitBreakers(entry->resource()->name());
1516
if (cbs.empty()) {
1617
return Sentinel::Slot::TokenResult::Ok();
1718
}
@@ -23,14 +24,13 @@ Sentinel::Slot::TokenResultSharedPtr CheckerSlot::Entry(
2324
return Sentinel::Slot::TokenResult::Ok();
2425
}
2526

26-
void CheckerSlot::Exit(const EntrySharedPtr& entry,
27-
const ResourceWrapperSharedPtr& resource, int count,
27+
void CheckerSlot::Exit(const EntrySharedPtr& entry, int count,
2828
const std::vector<absl::any>& params) {}
2929

3030
// CompleteStatSlot
3131

3232
Sentinel::Slot::TokenResultSharedPtr CompleteStatSlot::Entry(
33-
const EntrySharedPtr& entry, const ResourceWrapperSharedPtr& resource,
33+
const EntrySharedPtr& entry,
3434
/*const*/ Stat::NodeSharedPtr& node, int count, int flag,
3535
const std::vector<absl::any>& params) {
3636
if (entry == nullptr || entry->context() == nullptr) {
@@ -43,13 +43,13 @@ Sentinel::Slot::TokenResultSharedPtr CompleteStatSlot::Entry(
4343
return prev_result;
4444
}
4545

46-
void CompleteStatSlot::Exit(const EntrySharedPtr& entry,
47-
const ResourceWrapperSharedPtr& resource, int count,
46+
void CompleteStatSlot::Exit(const EntrySharedPtr& entry, int count,
4847
const std::vector<absl::any>& params) {
4948
if (entry == nullptr || entry->HasBlockError()) {
5049
return;
5150
}
52-
auto cbs = RuleManager::GetInstance().GetCircuitBreakers(resource->name());
51+
auto cbs =
52+
RuleManager::GetInstance().GetCircuitBreakers(entry->resource()->name());
5353
if (cbs.empty()) {
5454
return;
5555
}

sentinel-core/circuitbreaker/slot.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@ class CheckerSlot : public Slot::RuleCheckerSlot {
1515
virtual ~CheckerSlot() = default;
1616

1717
Sentinel::Slot::TokenResultSharedPtr Entry(
18-
const EntrySharedPtr& entry, const ResourceWrapperSharedPtr& resource,
19-
Stat::NodeSharedPtr& node, int count, int flag,
20-
const std::vector<absl::any>& params) override;
21-
void Exit(const EntrySharedPtr& entry,
22-
const ResourceWrapperSharedPtr& resource, int count,
18+
const EntrySharedPtr& entry, Stat::NodeSharedPtr& node, int count,
19+
int flag, const std::vector<absl::any>& params) override;
20+
void Exit(const EntrySharedPtr& entry, int count,
2321
const std::vector<absl::any>& params) override;
2422
const std::string& Name() const override { return name_; };
2523

@@ -34,11 +32,10 @@ class CompleteStatSlot : public Slot::StatsSlot {
3432

3533
const std::string& Name() const override { return name_; };
3634
Sentinel::Slot::TokenResultSharedPtr Entry(
37-
const EntrySharedPtr& entry, const ResourceWrapperSharedPtr& resource,
35+
const EntrySharedPtr& entry,
3836
/*const*/ Stat::NodeSharedPtr& node, int count, int flag,
3937
const std::vector<absl::any>& params) override;
40-
void Exit(const EntrySharedPtr& entry,
41-
const ResourceWrapperSharedPtr& resource, int count,
38+
void Exit(const EntrySharedPtr& entry, int count,
4239
const std::vector<absl::any>& params) override;
4340

4441
private:

sentinel-core/circuitbreaker/slot_test.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ Sentinel::Slot::TokenResultSharedPtr Entry_And_Exit(
2121
const EntrySharedPtr& entry, const ResourceWrapperSharedPtr& resource,
2222
Stat::NodeSharedPtr& node, int count, int flag,
2323
const std::vector<absl::any>& params) {
24-
auto result = slot_checker.Entry(entry, resource, node, count, flag, params);
24+
auto result = slot_checker.Entry(entry, node, count, flag, params);
2525
EXPECT_EQ(Sentinel::Slot::TokenStatus::RESULT_STATUS_OK, result->status());
26-
slot_complete.Entry(entry, resource, node, count, flag, params);
27-
slot_complete.Exit(entry, resource, count, params);
26+
slot_complete.Entry(entry, node, count, flag, params);
27+
slot_complete.Exit(entry, count, params);
2828

2929
return result;
3030
}
@@ -78,13 +78,13 @@ TEST(CircuitBreakerSlotTest, CircuitBreakerErrorRatioTest) {
7878
sleep(1);
7979

8080
// Switch state to kHalfOpen
81-
auto result = slot_checker.Entry(entry, resource, node, 1, 0, myParams);
81+
auto result = slot_checker.Entry(entry, node, 1, 0, myParams);
8282
EXPECT_EQ(Sentinel::Slot::TokenStatus::RESULT_STATUS_OK, result->status());
8383
EXPECT_EQ(cbs[0]->CurrentState(), State::kHalfOpen);
8484

8585
// Switch state to kClosed
86-
slot_complete.Entry(entry, resource, node, 1, 0, myParams);
87-
slot_complete.Exit(entry, resource, 1, myParams);
86+
slot_complete.Entry(entry, node, 1, 0, myParams);
87+
slot_complete.Exit(entry, 1, myParams);
8888
EXPECT_EQ(cbs[0]->CurrentState(), State::kClosed);
8989

9090
m.LoadRules({});
@@ -141,13 +141,13 @@ TEST(CircuitBreakerSlotTest, CircuitBreakerSlowRatioTest) {
141141
sleep(1);
142142

143143
// Switch state to kHalfOpen
144-
auto result = slot_checker.Entry(entry, resource, node, 1, 0, myParams);
144+
auto result = slot_checker.Entry(entry, node, 1, 0, myParams);
145145
EXPECT_EQ(Sentinel::Slot::TokenStatus::RESULT_STATUS_OK, result->status());
146146
EXPECT_EQ(cbs[0]->CurrentState(), State::kHalfOpen);
147147

148148
// Switch state to kClosed
149-
slot_complete.Entry(entry, resource, node, 1, 0, myParams);
150-
slot_complete.Exit(entry, resource, 1, myParams);
149+
slot_complete.Entry(entry, node, 1, 0, myParams);
150+
slot_complete.Exit(entry, 1, myParams);
151151
EXPECT_EQ(cbs[0]->CurrentState(), State::kClosed);
152152

153153
m.LoadRules({});

sentinel-core/common/constants.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ static constexpr const char* kLimitOriginOther = "other";
1212
static constexpr const char* kDefaultContextName = "sentinel_default_context";
1313

1414
static constexpr int kMaxAllowedRt = 4900;
15-
static constexpr int kMaxResourceSize = 6000;
15+
static constexpr int kMaxResourceSize = 10000;
16+
static constexpr int kMaxTagSize = 1000;
1617

1718
}; // namespace Constants
1819
} // namespace Sentinel

sentinel-core/common/entry.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ class Entry {
2727
std::chrono::milliseconds create_time() const { return create_time_; }
2828
EntryContextSharedPtr context() const { return context_; }
2929
Stat::NodeSharedPtr cur_node() const { return cur_node_; }
30-
Stat::NodeSharedPtr origin_node() const { return origin_node_; }
3130
int64_t rt() const { return rt_; }
3231
std::vector<absl::any> params() const { return params_; }
3332
bool exited() const { return exited_; }
@@ -39,7 +38,6 @@ class Entry {
3938
void set_error(const std::string& message) { error_ = message; }
4039
void set_block_error(const std::string& message) { block_error_ = message; }
4140
void set_cur_node(const Stat::NodeSharedPtr& node) { cur_node_ = node; }
42-
void set_origin_node(const Stat::NodeSharedPtr& node) { origin_node_ = node; }
4341
void set_params(const std::vector<absl::any>&& params) { params_ = params; }
4442

4543
private:
@@ -52,7 +50,6 @@ class Entry {
5250
std::string error_{};
5351
std::string block_error_{};
5452
Stat::NodeSharedPtr cur_node_;
55-
Stat::NodeSharedPtr origin_node_;
5653
std::vector<absl::any> params_;
5754
};
5855

sentinel-core/common/entry_context.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ namespace Sentinel {
1111
class EntryContext {
1212
public:
1313
explicit EntryContext(const std::string& name) : EntryContext(name, "") {}
14-
EntryContext(const std::string& name, const std::string& origin)
15-
: name_(name), origin_(origin) {}
14+
EntryContext(const std::string& name, const std::string& tag)
15+
: name_(name), tag_(tag) {}
1616

1717
const std::string& name() const { return name_; };
18-
const std::string& origin() const { return origin_; };
18+
const std::string& tag() const { return tag_; };
19+
Stat::NodeSharedPtr tag_node() { return tag_node_; }
1920

2021
const Slot::TokenResultSharedPtr& last_token_result() const {
2122
return last_token_result_;
@@ -26,10 +27,13 @@ class EntryContext {
2627
void set_last_token_result(const Slot::TokenResultSharedPtr& r) {
2728
last_token_result_ = r;
2829
}
30+
void set_tag_node(Stat::NodeSharedPtr& node) { tag_node_ = node; }
2931

3032
private:
3133
const std::string name_;
32-
const std::string origin_;
34+
// Maybe multiple tags in the future, using vector instead of string.
35+
const std::string tag_;
36+
Stat::NodeSharedPtr tag_node_;
3337

3438
Slot::TokenResultSharedPtr last_token_result_;
3539
};

sentinel-core/common/entry_result.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ bool EntryResult::Exit(int count) {
1616
Slot::SlotChainSharedPtr chain = Slot::GetGlobalSlotChain();
1717
if (chain != nullptr) {
1818
// NOTE: keep consistent with exit operation in SphU::Entry when blocked.
19-
chain->Exit(entry_, entry_->resource(), count, params);
19+
chain->Exit(entry_, count, params);
2020
}
2121
entry_->exited_ = true;
2222
return true;

sentinel-core/flow/flow_rule_checker.cc

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Slot::TokenResultSharedPtr FlowRuleChecker::PassLocalCheck(
2828
const FlowRule& rule, const EntrySharedPtr& entry,
2929
const Stat::NodeSharedPtr& node, int count, int flag) {
3030
Stat::NodeSharedPtr selected_node =
31-
SelectNodeByRelStrategy(rule, entry, node);
31+
selectNodeByRequesterAndStrategy(rule, entry, node);
3232
if (selected_node == nullptr) {
3333
return Slot::TokenResult::Ok();
3434
}
@@ -40,8 +40,43 @@ Slot::TokenResultSharedPtr FlowRuleChecker::PassLocalCheck(
4040
return controller->CanPass(selected_node, count, flag);
4141
}
4242

43+
Stat::NodeSharedPtr FlowRuleChecker::selectNodeByRequesterAndStrategy(
44+
const FlowRule& rule, const EntrySharedPtr& entry,
45+
const Stat::NodeSharedPtr& node) {
46+
FlowRuleManager& m = FlowRuleManager::GetInstance();
47+
std::string tag = entry->context()->tag();
48+
std::string limit_origin = rule.limit_origin();
49+
FlowRelationStrategy strategy = rule.strategy();
50+
Stat::NodeSharedPtr tag_node = entry->context()->tag_node();
51+
52+
if ((tag == limit_origin) && IsValidTag(tag)) {
53+
if (strategy == FlowRelationStrategy::kDirect) {
54+
// When tag matches, return tag node.
55+
return tag_node;
56+
}
57+
return SelectNodeByRelStrategy(rule, entry, node);
58+
} else if (limit_origin == Constants::kLimitOriginDefault) {
59+
if (strategy == FlowRelationStrategy::kDirect) {
60+
// When rule contains default tag, which means all request should follow
61+
// rule's limit count.
62+
return node;
63+
}
64+
return SelectNodeByRelStrategy(rule, entry, node);
65+
} else if ((limit_origin == Constants::kLimitOriginOther) &&
66+
m.IsTagNotInFlowRuleList(rule.resource(), tag)) {
67+
if (strategy == FlowRelationStrategy::kDirect) {
68+
// When rule contains other tag, which means all request except this tag
69+
// should follow this rule.
70+
return tag_node;
71+
}
72+
return SelectNodeByRelStrategy(rule, entry, node);
73+
}
74+
75+
return nullptr;
76+
}
77+
4378
Stat::NodeSharedPtr FlowRuleChecker::SelectNodeByRelStrategy(
44-
const FlowRule& rule, const EntrySharedPtr&,
79+
const FlowRule& rule, const EntrySharedPtr& entry,
4580
const Stat::NodeSharedPtr& node) {
4681
const std::string& ref_resource = rule.ref_resource();
4782
auto rel_strategy = rule.strategy();
@@ -50,8 +85,14 @@ Stat::NodeSharedPtr FlowRuleChecker::SelectNodeByRelStrategy(
5085
return Stat::ResourceNodeStorage::GetInstance().GetClusterNode(
5186
ref_resource);
5287
}
88+
5389
return node;
5490
}
5591

92+
bool FlowRuleChecker::IsValidTag(const std::string& tag) {
93+
return !tag.empty() && (tag != Constants::kLimitOriginDefault) &&
94+
(tag != Constants::kLimitOriginOther);
95+
}
96+
5697
} // namespace Flow
5798
} // namespace Sentinel

sentinel-core/flow/flow_rule_checker.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ class FlowRuleChecker {
2727
const Stat::NodeSharedPtr& node,
2828
int count, int flag);
2929

30+
Stat::NodeSharedPtr selectNodeByRequesterAndStrategy(
31+
const FlowRule& rule, const EntrySharedPtr& entry,
32+
const Stat::NodeSharedPtr& node);
33+
3034
Stat::NodeSharedPtr SelectNodeByRelStrategy(const FlowRule& rule,
3135
const EntrySharedPtr& entry,
3236
const Stat::NodeSharedPtr& node);
37+
bool IsValidTag(const std::string& tag);
3338
};
3439

3540
} // namespace Flow

0 commit comments

Comments
 (0)