Skip to content

Commit

Permalink
Feature: implement overload controller plugin token bucket trpc-group…
Browse files Browse the repository at this point in the history
  • Loading branch information
AntiBargu committed Sep 14, 2024
1 parent d2a8220 commit 113e2f0
Show file tree
Hide file tree
Showing 12 changed files with 757 additions and 0 deletions.
6 changes: 6 additions & 0 deletions trpc/overload_control/overload_control_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ constexpr char kOverloadctrlThrottler[] = "overloadctrl_throttler";
/// @brief Key for request priority in trpc framework.
constexpr char kTransinfoKeyTrpcPriority[] = "trpc-priority";

/// @brief Name of overload protection limiter based on token bucket.
constexpr char kSlidingWindowLimiterName[] = "sliding_window_limiter";

/// @brief Name of monitoring dimensions for request-based concurrent overload protection rate limiter.
constexpr char kOverloadctrlSlidingWindowLimiter[] = "overloadctrl_sliding_window_limiter";

} // namespace trpc::overload_control

#endif
99 changes: 99 additions & 0 deletions trpc/overload_control/sliding_window_limiter/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
licenses(["notice"])

package(default_visibility = ["//visibility:public"])

cc_library(
name = "sliding_window_limiter_conf",
srcs = ["sliding_window_limiter_conf.cc"],
hdrs = ["sliding_window_limiter_conf.h"],
defines = [] +
select({
"//trpc:trpc_include_overload_control": ["TRPC_BUILD_INCLUDE_OVERLOAD_CONTROL"],
"//conditions:default": [],
}),
visibility = [
"//visibility:public",
],
deps = [
"//trpc/log:trpc_log",
"//trpc/overload_control:overload_control_defs",
"@com_github_jbeder_yaml_cpp//:yaml-cpp",
],
)

cc_test(
name = "sliding_window_limiter_conf_test",
srcs = ["sliding_window_limiter_conf_test.cc"],
deps = [
":sliding_window_limiter_conf",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "sliding_window_overload_controller",
srcs = ["sliding_window_overload_controller.cc"],
hdrs = ["sliding_window_overload_controller.h"],
defines = [] +
select({
"//trpc:trpc_include_overload_control": ["TRPC_BUILD_INCLUDE_OVERLOAD_CONTROL"],
"//conditions:default": [],
}),
visibility = [
"//visibility:public",
],
deps = [
":sliding_window_limiter_conf",
"//trpc/overload_control:overload_control_defs",
"//trpc/overload_control:server_overload_controller",
"//trpc/overload_control/flow_control:smooth_limiter",
],
)

cc_test(
name = "sliding_window_overload_controller_test",
srcs = ["sliding_window_overload_controller_test.cc"],
deps = [
":sliding_window_limiter_conf",
":sliding_window_overload_controller",
"//trpc/codec/testing:protocol_testing",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "sliding_window_limiter_server_filter",
srcs = ["sliding_window_limiter_server_filter.cc"],
hdrs = ["sliding_window_limiter_server_filter.h"],
defines = [] +
select({
"//trpc:trpc_include_overload_control": ["TRPC_BUILD_INCLUDE_OVERLOAD_CONTROL"],
"//conditions:default": [],
}),
visibility = ["//visibility:public"],
deps = [
":sliding_window_limiter_conf",
":sliding_window_overload_controller",
"//trpc/filter",
"//trpc/log:trpc_log",
"//trpc/overload_control:overload_control_defs",
"//trpc/overload_control/common:report",
"//trpc/server:server_context",
"//trpc/server:service_impl",
"//trpc/util:ref_ptr",
],
)

cc_test(
name = "sliding_window_limiter_server_filter_test",
srcs = ["sliding_window_limiter_server_filter_test.cc"],
data = ["sliding_window_overload_ctrl.yaml"],
deps = [
":sliding_window_limiter_server_filter",
"//trpc/codec/testing:protocol_testing",
"//trpc/common/config:trpc_config",
"//trpc/filter:filter_manager",
"@com_google_googletest//:gtest_main",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
*
* Tencent is pleased to support the open source community by making
* tRPC available.
*
* Copyright (C) 2024 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifdef TRPC_BUILD_INCLUDE_OVERLOAD_CONTROL

#include "trpc/log/trpc_log.h"

#include "trpc/overload_control/sliding_window_limiter/sliding_window_limiter_conf.h"

namespace trpc::overload_control {

void SlidingWindowLimiterControlConf::Display() const {
TRPC_FMT_DEBUG("----------SlidingWindowLimiterControlConf---------------");

TRPC_FMT_DEBUG("limit: {}", limit);
TRPC_FMT_DEBUG("window_size: {}", window_size);
TRPC_FMT_DEBUG("is_report: {}", is_report);
}
} // namespace trpc::overload_control

namespace YAML {

YAML::Node convert<trpc::overload_control::SlidingWindowLimiterControlConf>::encode(
const trpc::overload_control::SlidingWindowLimiterControlConf& config) {
YAML::Node node;

node["limit"] = config.limit;
node["window_size"] = config.window_size;
node["is_report"] = config.is_report;

return node;
}

bool convert<trpc::overload_control::SlidingWindowLimiterControlConf>::decode(
const YAML::Node& node, trpc::overload_control::SlidingWindowLimiterControlConf& config) {
if (node["limit"]) {
config.limit = node["limit"].as<int64_t>();
}
if (node["window_size"]) {
config.window_size = node["window_size"].as<int32_t>();
}
if (node["is_report"]) {
config.is_report = node["is_report"].as<bool>();
}

return true;
}

} // namespace YAML

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
*
* Tencent is pleased to support the open source community by making
* tRPC available.
*
* Copyright (C) 2024 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifdef TRPC_BUILD_INCLUDE_OVERLOAD_CONTROL

#pragma once

#include "yaml-cpp/yaml.h"

#include "trpc/overload_control/overload_control_defs.h"

namespace trpc::overload_control {

/// @brief sliding_window concurrent control configuration.
struct SlidingWindowLimiterControlConf {
// Maximum number of requests per second.
int64_t limit{1000};
// Window size
int32_t window_size{100};
// Whether to report the judgment result to the monitoring plugin.
bool is_report{false};

/// @brief Display the value of the configuration field.
void Display() const;
};
} // namespace trpc::overload_control

namespace YAML {

template <>
struct convert<trpc::overload_control::SlidingWindowLimiterControlConf> {
static YAML::Node encode(const trpc::overload_control::SlidingWindowLimiterControlConf& config);

static bool decode(const YAML::Node& node, trpc::overload_control::SlidingWindowLimiterControlConf& config);
};

} // namespace YAML

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
*
* Tencent is pleased to support the open source community by making
* tRPC available.
*
* Copyright (C) 2024 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef TRPC_BUILD_INCLUDE_OVERLOAD_CONTROL

#include "trpc/overload_control/sliding_window_limiter/sliding_window_limiter_conf.h"

#include "gtest/gtest.h"

namespace trpc::overload_control {
namespace testing {

TEST(SlidingWindowLimiterControlConf, All) {
SlidingWindowLimiterControlConf conf;
ASSERT_EQ(conf.limit, 1000);
ASSERT_EQ(conf.window_size, 100);
ASSERT_EQ(conf.is_report, false);

YAML::convert<SlidingWindowLimiterControlConf> concurr_yaml;

conf.limit = 20000;
conf.window_size = 2000;

YAML::Node concurr_node = concurr_yaml.encode(conf);

SlidingWindowLimiterControlConf decode_conf;

ASSERT_EQ(concurr_yaml.decode(concurr_node, decode_conf), true);

ASSERT_EQ(decode_conf.limit, 20000);
ASSERT_EQ(decode_conf.window_size, 2000);

decode_conf.Display();
}

} // namespace testing
} // namespace trpc::overload_control

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
*
* Tencent is pleased to support the open source community by making
* tRPC available.
*
* Copyright (C) 2024 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifdef TRPC_BUILD_INCLUDE_OVERLOAD_CONTROL

#include "trpc/overload_control/sliding_window_limiter/sliding_window_limiter_server_filter.h"

#include "trpc/common/config/trpc_config.h"
#include "trpc/log/trpc_log.h"
#include "trpc/overload_control/common/report.h"

namespace trpc::overload_control {

int SlidingWindowLimiterServerFilter::Init() {
bool ok = TrpcConfig::GetInstance()->GetPluginConfig<SlidingWindowLimiterControlConf>(
kOverloadCtrConfField, kSlidingWindowLimiterName, sliding_window_conf_);
if (!ok) {
TRPC_FMT_DEBUG("SlidingWindowLimiterServerFilter read config failed, will use a default config");
}
sliding_window_conf_.Display();

service_controller_ = std::make_unique<SlidingWindowOverloadController>(
sliding_window_conf_.limit, sliding_window_conf_.window_size, sliding_window_conf_.is_report);

return 0;
}

std::vector<FilterPoint> SlidingWindowLimiterServerFilter::GetFilterPoint() {
return {
FilterPoint::SERVER_PRE_SCHED_RECV_MSG,
// This tracking point is not used, but tracking points must be paired, so it is added here.
FilterPoint::SERVER_POST_SCHED_RECV_MSG,
};
}

void SlidingWindowLimiterServerFilter::operator()(FilterStatus& status, FilterPoint point,
const ServerContextPtr& context) {
switch (point) {
case FilterPoint::SERVER_PRE_SCHED_RECV_MSG: {
OnRequest(status, context);
break;
}
default: {
break;
}
}
}

void SlidingWindowLimiterServerFilter::OnRequest(FilterStatus& status, const ServerContextPtr& context) {
if (TRPC_UNLIKELY(!context->GetStatus().OK())) {
// If it is already a dirty request, it will not be processed further to ensure that the first error code is
// not overwritten.
return;
}

bool passed = service_controller_->BeforeSchedule(context);
if (!passed) {
context->SetStatus(
Status(TrpcRetCode::TRPC_SERVER_OVERLOAD_ERR, 0, "rejected by server token bucket limiter overload control"));
status = FilterStatus::REJECT;
}

// Report the result.
if (sliding_window_conf_.is_report) {
OverloadInfo infos;
infos.attr_name = kOverloadctrlSlidingWindowLimiter;
infos.report_name = fmt::format("/{}/{}", context->GetCalleeName(), context->GetFuncName());
infos.tags[kOverloadctrlPass] = (passed == true ? 1 : 0);
infos.tags[kOverloadctrlLimited] = (passed == false ? 1 : 0);
Report::GetInstance()->ReportOverloadInfo(infos);
}
}

} // namespace trpc::overload_control

#endif
Loading

0 comments on commit 113e2f0

Please sign in to comment.