Skip to content

Commit c53f917

Browse files
authored
feat: inbound only graceful draining (envoyproxy#38430)
Trying envoyproxy#37873 again to get to the bottom of the flakes that caused us to need to revert. This got a lot more complex after envoyproxy#38333, so I may need @yanavlasov to help me out with the proper semantics Commit Message: ``` Fixes envoyproxy#35020. The inbound_only query param for the drain_listeners admin endpoint doesn't work with the graceful query parameter. As a result, outbound listeners will send connection: close headers to upstreams which is undesired. This PR adds the ability for drain_manager to drain in a single direction. ``` Additional Description: Risk Level: Medium Testing: Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] --------- Signed-off-by: Keith Mattix II <[email protected]>
1 parent 5ff9f03 commit c53f917

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+669
-261
lines changed

.bazelrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# leave room for compiler/linker.
99
# The number 3G is chosen heuristically to both support large VM and small VM with RBE.
1010
# Startup options cannot be selected via config.
11+
# TODO: Adding just to test android
1112
startup --host_jvm_args=-Xmx3g
1213

1314
common --noenable_bzlmod

changelogs/current.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ new_features:
146146
change: |
147147
Added support for outlier detection in UDP proxy. This change can be temporarily reverted by setting runtime guard
148148
``envoy.reloadable_features.enable_udp_proxy_outlier_detection`` to ``false``.
149+
- area: admin
150+
change: |
151+
Add support for the inbound_only and graceful query params of /drain_listeners to be used together by
152+
implementing directional draining in DrainManager.
149153
- area: http
150154
change: |
151155
Added alpha support for asynchronous load balancing. See

docs/root/operations/admin.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,8 @@ modify different aspects of the server:
363363
364364
:ref:`Drains <arch_overview_draining>` all inbound listeners. ``traffic_direction`` field in
365365
:ref:`Listener <envoy_v3_api_msg_config.listener.v3.Listener>` is used to determine whether a listener
366-
is inbound or outbound.
366+
is inbound or outbound. May not be effective for network filters like :ref:`Redis <config_network_filters_redis_proxy>`,
367+
:ref:`Mongo <config_network_filters_mongo_proxy>`, or :ref:`Thrift <config_network_filters_thrift_proxy>`.
367368

368369
.. http:post:: /drain_listeners?graceful
369370

envoy/network/drain_decision.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@
1212
namespace Envoy {
1313
namespace Network {
1414

15+
enum class DrainDirection {
16+
/**
17+
* Not draining yet. Default value, should not be externally set.
18+
*/
19+
None = 0,
20+
21+
/**
22+
* Drain inbound connections only.
23+
*/
24+
InboundOnly,
25+
26+
/**
27+
* Drain both inbound and outbound connections.
28+
*/
29+
All,
30+
};
31+
1532
class DrainDecision {
1633
public:
1734
using DrainCloseCb = std::function<absl::Status(std::chrono::milliseconds)>;
@@ -21,8 +38,9 @@ class DrainDecision {
2138
/**
2239
* @return TRUE if a connection should be drained and closed. It is up to individual network
2340
* filters to determine when this should be called for the least impact possible.
41+
* @param direction supplies the direction for which the caller is checking drain close.
2442
*/
25-
virtual bool drainClose() const PURE;
43+
virtual bool drainClose(DrainDirection scope) const PURE;
2644

2745
/**
2846
* @brief Register a callback to be called proactively when a drain decision enters into a
@@ -34,7 +52,8 @@ class DrainDecision {
3452
* @return handle to remove callback
3553
*/
3654
ABSL_MUST_USE_RESULT
37-
virtual Common::CallbackHandlePtr addOnDrainCloseCb(DrainCloseCb cb) const PURE;
55+
virtual Common::CallbackHandlePtr addOnDrainCloseCb(DrainDirection scope,
56+
DrainCloseCb cb) const PURE;
3857
};
3958

4059
} // namespace Network

envoy/server/drain_manager.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,17 @@ class DrainManager : public Network::DrainDecision, public ThreadLocal::ThreadLo
4242

4343
/**
4444
* Invoked to begin the drain procedure. (Making drain close operations more likely).
45+
* @param direction is the direction of the drain.
4546
* @param drain_complete_cb will be invoked once the drain sequence is finished. The parameter is
4647
* optional and can be an unassigned function.
4748
*/
48-
virtual void startDrainSequence(std::function<void()> drain_complete_cb) PURE;
49+
virtual void startDrainSequence(Network::DrainDirection direction,
50+
std::function<void()> drain_complete_cb) PURE;
4951

5052
/**
51-
* @return whether the drain sequence has started.
53+
* @return whether the drain sequence has started for this direction.
5254
*/
53-
virtual bool draining() const PURE;
55+
virtual bool draining(Network::DrainDirection) const PURE;
5456

5557
/**
5658
* Invoked in the newly launched primary process to begin the parent shutdown sequence. At the end

mobile/library/jni/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ cc_binary(
141141
"-lm",
142142
# See libpthread below.
143143
"-L$(GENDIR)/{}".format(package_name()),
144+
"-latomic",
144145
] + select({
145146
"@envoy//bazel:dbg_build": ["-Wl,--build-id=sha1"],
146147
"//conditions:default": [],

mobile/test/jni/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ cc_library(
6464
cc_binary(
6565
name = "libenvoy_jni_http_test_server_factory.so",
6666
testonly = True,
67+
linkopts = [
68+
"-latomic",
69+
],
6770
linkshared = True,
6871
deps = [
6972
":jni_http_test_server_factory_lib",
@@ -98,6 +101,9 @@ cc_library(
98101
cc_binary(
99102
name = "libenvoy_jni_http_proxy_test_server_factory.so",
100103
testonly = True,
104+
linkopts = [
105+
"-latomic",
106+
],
101107
linkshared = True,
102108
deps = [
103109
":jni_http_proxy_test_server_factory_lib",
@@ -109,6 +115,9 @@ cc_binary(
109115
cc_binary(
110116
name = "libenvoy_jni_with_test_extensions.so",
111117
testonly = True,
118+
linkopts = [
119+
"-latomic",
120+
],
112121
linkshared = True,
113122
deps = [
114123
":envoy_jni_with_test_extensions_lib",
@@ -140,6 +149,9 @@ cc_library(
140149
cc_binary(
141150
name = "libenvoy_jni_with_test_and_listener_extensions.so",
142151
testonly = True,
152+
linkopts = [
153+
"-latomic",
154+
],
143155
linkshared = True,
144156
deps = [
145157
":envoy_jni_with_test_and_listener_extensions_lib",

mobile/test/performance/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ envoy_mobile_package()
77
envoy_cc_binary(
88
name = "test_binary_size",
99
srcs = ["test_binary_size.cc"],
10+
linkopts = [
11+
"-latomic",
12+
],
1013
repository = "@envoy",
1114
stamped = True,
1215
deps = ["//library/common:internal_engine_lib"],

source/common/http/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ envoy_cc_library(
400400
"//source/common/stats:timespan_lib",
401401
"//source/common/stream_info:stream_info_lib",
402402
"//source/common/tracing:http_tracer_lib",
403+
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
403404
"@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg_cc_proto",
404405
"@envoy_api//envoy/type/v3:pkg_cc_proto",
405406
],

source/common/http/conn_manager_impl.cc

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "envoy/buffer/buffer.h"
1313
#include "envoy/common/time.h"
14+
#include "envoy/config/core/v3/base.pb.h"
1415
#include "envoy/event/dispatcher.h"
1516
#include "envoy/event/scaled_range_timer_manager.h"
1617
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h"
@@ -98,14 +99,12 @@ ConnectionManagerImpl::generateListenerStats(const std::string& prefix, Stats::S
9899
return {CONN_MAN_LISTENER_STATS(POOL_COUNTER_PREFIX(scope, prefix))};
99100
}
100101

101-
ConnectionManagerImpl::ConnectionManagerImpl(ConnectionManagerConfigSharedPtr config,
102-
const Network::DrainDecision& drain_close,
103-
Random::RandomGenerator& random_generator,
104-
Http::Context& http_context, Runtime::Loader& runtime,
105-
const LocalInfo::LocalInfo& local_info,
106-
Upstream::ClusterManager& cluster_manager,
107-
Server::OverloadManager& overload_manager,
108-
TimeSource& time_source)
102+
ConnectionManagerImpl::ConnectionManagerImpl(
103+
ConnectionManagerConfigSharedPtr config, const Network::DrainDecision& drain_close,
104+
Random::RandomGenerator& random_generator, Http::Context& http_context,
105+
Runtime::Loader& runtime, const LocalInfo::LocalInfo& local_info,
106+
Upstream::ClusterManager& cluster_manager, Server::OverloadManager& overload_manager,
107+
TimeSource& time_source, envoy::config::core::v3::TrafficDirection direction)
109108
: config_(std::move(config)), stats_(config_->stats()),
110109
conn_length_(new Stats::HistogramCompletableTimespanImpl(
111110
stats_.named_.downstream_cx_length_ms_, time_source)),
@@ -128,6 +127,7 @@ ConnectionManagerImpl::ConnectionManagerImpl(ConnectionManagerConfigSharedPtr co
128127
/*proxy_status_config=*/config_->proxyStatusConfig())),
129128
max_requests_during_dispatch_(
130129
runtime_.snapshot().getInteger(ConnectionManagerImpl::MaxRequestsPerIoCycle, UINT32_MAX)),
130+
direction_(direction),
131131
allow_upstream_half_close_(Runtime::runtimeFeatureEnabled(
132132
"envoy.reloadable_features.allow_multiplexed_upstream_half_close")) {
133133
ENVOY_LOG_ONCE_IF(
@@ -1799,10 +1799,19 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ResponseHeaderMap& heade
17991799
connection_manager_.stats_.named_.downstream_cx_overload_disable_keepalive_.inc();
18001800
}
18011801

1802+
// If we're an inbound listener, then we should drain even if the drain direction is inbound only.
1803+
// If not, then we only drain if the drain direction is all.
1804+
Network::DrainDirection drain_scope =
1805+
connection_manager_.direction_ == envoy::config::core::v3::TrafficDirection::INBOUND
1806+
? Network::DrainDirection::InboundOnly
1807+
: Network::DrainDirection::All;
1808+
18021809
// See if we want to drain/close the connection. Send the go away frame prior to encoding the
1803-
// header block.
1810+
// header block. Only drain if the drain direction is not inbound only or the connection is
1811+
// inbound.
18041812
if (connection_manager_.drain_state_ == DrainState::NotDraining &&
1805-
(connection_manager_.drain_close_.drainClose() || drain_connection_due_to_overload)) {
1813+
(connection_manager_.drain_close_.drainClose(drain_scope) ||
1814+
drain_connection_due_to_overload)) {
18061815

18071816
// This doesn't really do anything for HTTP/1.1 other then give the connection another boost
18081817
// of time to race with incoming requests. For HTTP/2 connections, send a GOAWAY frame to

0 commit comments

Comments
 (0)