Skip to content

Commit 5ff9f03

Browse files
Set RCD for 100% drop_overload case as unconditional_drop_overload (envoyproxy#38408)
This is a follow up commit of drop_overload support:envoyproxy#30827. It is observed that in some situations, EDS sends drop_overload ratio as 100% for some clusters do not have healthy endpoints in the cluster. For such cases, it is preferred that the RCD of the local reply set to "unconditional drop overload" to make it a little bit different from the normal "drop overload" case. --------- Signed-off-by: Yanjun Xiang <[email protected]>
1 parent 68e64b4 commit 5ff9f03

File tree

12 files changed

+86
-5
lines changed

12 files changed

+86
-5
lines changed

api/envoy/config/accesslog/v3/accesslog.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ message ResponseFlagFilter {
260260
in: "DF"
261261
in: "DO"
262262
in: "DR"
263+
in: "UDO"
263264
}
264265
}
265266
}];

docs/root/configuration/observability/access_log/usage.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ HTTP only
569569
**DnsResolutionFailed**, **DF**, The request was terminated due to DNS resolution failure.
570570
**DropOverload**, **DO**, The request was terminated in addition to 503 response code due to :ref:`drop_overloads<envoy_v3_api_field_config.endpoint.v3.ClusterLoadAssignment.Policy.drop_overloads>`.
571571
**DownstreamRemoteReset**, **DR**, The response details are ``http2.remote_reset`` or ``http2.remote_refuse``.
572+
**UnconditionalDropOverload**, **UDO**, The request was terminated in addition to 503 response code due to :ref:`drop_overloads<envoy_v3_api_field_config.endpoint.v3.ClusterLoadAssignment.Policy.drop_overloads>` is set to 100%.
572573

573574
UDP
574575
Not implemented ("-").

envoy/stream_info/stream_info.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ enum CoreResponseFlag : uint16_t {
9595
DropOverLoad,
9696
// Downstream remote codec level reset was received on the stream.
9797
DownstreamRemoteReset,
98+
// Unconditionally drop all traffic due to drop_overload is set to 100%.
99+
UnconditionalDropOverload,
98100
// ATTENTION: MAKE SURE THIS REMAINS EQUAL TO THE LAST FLAG.
99-
LastFlag = DownstreamRemoteReset,
101+
LastFlag = UnconditionalDropOverload,
100102
};
101103

102104
class ResponseFlagUtils;
@@ -196,6 +198,9 @@ struct ResponseCodeDetailValues {
196198
const std::string MaintenanceMode = "maintenance_mode";
197199
// The request was rejected by the router filter because the DROP_OVERLOAD configuration.
198200
const std::string DropOverload = "drop_overload";
201+
// The request was rejected by the router filter because the DROP_OVERLOAD configuration is set to
202+
// 100%.
203+
const std::string UnconditionalDropOverload = "unconditional_drop_overload";
199204
// The request was rejected by the router filter because there was no healthy upstream found.
200205
const std::string NoHealthyUpstream = "no_healthy_upstream";
201206
// The request was forwarded upstream but the response timed out.

source/common/http/headers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ class HeaderValues {
178178
const LowerCaseString EnvoyOriginalPath{absl::StrCat(prefix(), "-original-path")};
179179
const LowerCaseString EnvoyOverloaded{absl::StrCat(prefix(), "-overloaded")};
180180
const LowerCaseString EnvoyDropOverload{absl::StrCat(prefix(), "-drop-overload")};
181+
const LowerCaseString EnvoyUnconditionalDropOverload{
182+
absl::StrCat(prefix(), "-unconditional-drop-overload")};
181183
const LowerCaseString EnvoyRateLimited{absl::StrCat(prefix(), "-ratelimited")};
182184
const LowerCaseString EnvoyRetryOn{absl::StrCat(prefix(), "-retry-on")};
183185
const LowerCaseString EnvoyRetryGrpcOn{absl::StrCat(prefix(), "-retry-grpc-on")};
@@ -286,6 +288,10 @@ class HeaderValues {
286288
const std::string True{"true"};
287289
} EnvoyDropOverloadValues;
288290

291+
struct {
292+
const std::string True{"true"};
293+
} EnvoyUnconditionalDropOverloadValues;
294+
289295
struct {
290296
const std::string True{"true"};
291297
} EnvoyRateLimitedValues;

source/common/router/router.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2229,6 +2229,29 @@ bool Filter::checkDropOverload(Upstream::ThreadLocalCluster& cluster,
22292229
if (cluster.dropOverload().value()) {
22302230
ENVOY_STREAM_LOG(debug, "Router filter: cluster DROP_OVERLOAD configuration: {}", *callbacks_,
22312231
cluster.dropOverload().value());
2232+
2233+
if (cluster.dropOverload().value() == 1.0) {
2234+
ENVOY_STREAM_LOG(
2235+
debug, "The configured DROP_OVERLOAD ratio is 100%, drop everything unconditionally.",
2236+
*callbacks_);
2237+
callbacks_->streamInfo().setResponseFlag(
2238+
StreamInfo::CoreResponseFlag::UnconditionalDropOverload);
2239+
chargeUpstreamCode(Http::Code::ServiceUnavailable, {}, true);
2240+
callbacks_->sendLocalReply(
2241+
Http::Code::ServiceUnavailable, "unconditional drop overload",
2242+
[modify_headers, this](Http::ResponseHeaderMap& headers) {
2243+
if (!config_->suppress_envoy_headers_) {
2244+
headers.addReference(Http::Headers::get().EnvoyUnconditionalDropOverload,
2245+
Http::Headers::get().EnvoyUnconditionalDropOverloadValues.True);
2246+
}
2247+
modify_headers(headers);
2248+
},
2249+
absl::nullopt, StreamInfo::ResponseCodeDetails::get().UnconditionalDropOverload);
2250+
2251+
cluster.info()->loadReportStats().upstream_rq_drop_overload_.inc();
2252+
return true;
2253+
}
2254+
22322255
if (config_->random_.bernoulli(cluster.dropOverload())) {
22332256
ENVOY_STREAM_LOG(debug, "The request is dropped by DROP_OVERLOAD", *callbacks_);
22342257
callbacks_->streamInfo().setResponseFlag(StreamInfo::CoreResponseFlag::DropOverLoad);

source/common/stream_info/utility.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ ResponseFlag ResponseFlagUtils::registerCustomFlag(absl::string_view custom_flag
8686

8787
const ResponseFlagUtils::ResponseFlagsVecType& ResponseFlagUtils::responseFlagsVec() {
8888
CONSTRUCT_ON_FIRST_USE(ResponseFlagsVecType, []() {
89-
static_assert(CoreResponseFlag::LastFlag == 28,
89+
static_assert(CoreResponseFlag::LastFlag == 29,
9090
"A flag has been added. Add the new flag to CORE_RESPONSE_FLAGS.");
9191

9292
responseFlagsVecInitialized() = true;

source/common/stream_info/utility.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class ResponseFlagUtils {
104104
constexpr static absl::string_view DNS_FAIL = "DF";
105105
constexpr static absl::string_view DROP_OVERLOAD = "DO";
106106
constexpr static absl::string_view DOWNSTREAM_REMOTE_RESET = "DR";
107+
constexpr static absl::string_view UNCONDITIONAL_DROP_OVERLOAD = "UDO";
107108

108109
constexpr static absl::string_view DOWNSTREAM_CONNECTION_TERMINATION_LONG =
109110
"DownstreamConnectionTermination";
@@ -140,6 +141,7 @@ class ResponseFlagUtils {
140141
constexpr static absl::string_view DNS_FAIL_LONG = "DnsResolutionFailed";
141142
constexpr static absl::string_view DROP_OVERLOAD_LONG = "DropOverload";
142143
constexpr static absl::string_view DOWNSTREAM_REMOTE_RESET_LONG = "DownstreamRemoteReset";
144+
constexpr static absl::string_view UNCONDITIONAL_DROP_OVERLOAD_LONG = "UnconditionalDropOverload";
143145

144146
static constexpr std::array CORE_RESPONSE_FLAGS{
145147
FlagStrings{FAILED_LOCAL_HEALTH_CHECK, FAILED_LOCAL_HEALTH_CHECK_LONG,
@@ -189,6 +191,8 @@ class ResponseFlagUtils {
189191
FlagStrings{DROP_OVERLOAD, DROP_OVERLOAD_LONG, CoreResponseFlag::DropOverLoad},
190192
FlagStrings{DOWNSTREAM_REMOTE_RESET, DOWNSTREAM_REMOTE_RESET_LONG,
191193
CoreResponseFlag::DownstreamRemoteReset},
194+
FlagStrings{UNCONDITIONAL_DROP_OVERLOAD, UNCONDITIONAL_DROP_OVERLOAD_LONG,
195+
CoreResponseFlag::UnconditionalDropOverload},
192196
};
193197

194198
private:

source/extensions/access_loggers/grpc/grpc_access_log_utils.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void Utility::responseFlagsToAccessLogResponseFlags(
4141
envoy::data::accesslog::v3::AccessLogCommon& common_access_log,
4242
const StreamInfo::StreamInfo& stream_info) {
4343

44-
static_assert(StreamInfo::CoreResponseFlag::LastFlag == 28,
44+
static_assert(StreamInfo::CoreResponseFlag::LastFlag == 29,
4545
"A flag has been added. Fix this code.");
4646

4747
if (stream_info.hasResponseFlag(StreamInfo::CoreResponseFlag::FailedLocalHealthCheck)) {

test/common/access_log/access_log_impl_test.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,7 @@ name: accesslog
10671067
- DF
10681068
- DO
10691069
- DR
1070+
- UDO
10701071
typed_config:
10711072
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
10721073
path: /dev/null

test/common/router/router_test.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,30 @@ TEST_F(RouterTest, DropOverloadDropped) {
859859
EXPECT_EQ(callbacks_.details(), "drop_overload");
860860
}
861861

862+
// UnconditionalDropOverload drop test
863+
TEST_F(RouterTest, UnconditionalDropOverloadDropped) {
864+
EXPECT_CALL(cm_.thread_local_cluster_, dropOverload()).WillRepeatedly(Return(UnitFloat(1.0)));
865+
Http::TestResponseHeaderMapImpl response_headers{{":status", "503"},
866+
{"content-length", "27"},
867+
{"content-type", "text/plain"},
868+
{"x-envoy-unconditional-drop-overload", "true"}};
869+
EXPECT_CALL(callbacks_, encodeHeaders_(HeaderMapEqualRef(&response_headers), false));
870+
EXPECT_CALL(callbacks_, encodeData(_, true));
871+
EXPECT_CALL(callbacks_.stream_info_,
872+
setResponseFlag(StreamInfo::CoreResponseFlag::UnconditionalDropOverload));
873+
874+
Http::TestRequestHeaderMapImpl headers;
875+
HttpTestUtility::addDefaultHeaders(headers);
876+
router_->decodeHeaders(headers, true);
877+
EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->load_report_stats_store_
878+
.counter("upstream_rq_drop_overload")
879+
.value());
880+
EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->load_report_stats_store_
881+
.counter("upstream_rq_dropped")
882+
.value());
883+
EXPECT_EQ(callbacks_.details(), "unconditional_drop_overload");
884+
}
885+
862886
TEST_F(RouterTest, ResponseCodeDetailsSetByUpstream) {
863887
NiceMock<Http::MockRequestEncoder> encoder1;
864888
Http::ResponseDecoder* response_decoder = nullptr;

0 commit comments

Comments
 (0)