Skip to content

Commit 2b2e63f

Browse files
committed
Enforce Active Connection limits
1. Throttle connections when there's no room in active conn queue 2. Adjust manage_active_queue() to not fail when the conn is already in active queue 3. Metrics for throttling 4. metrics for timing out connections due to default inactivity timeout
1 parent 4638ddc commit 2b2e63f

File tree

7 files changed

+58
-11
lines changed

7 files changed

+58
-11
lines changed

doc/admin-guide/monitoring/statistics/core/network-io.en.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,17 @@ Network I/O
6060
.. ts:stat:: global proxy.process.net.connections_currently_open integer
6161
:type: counter
6262

63+
.. ts:stat:: global proxy.process.net.connections_throttled_in integer
64+
:type: counter
65+
66+
.. ts:stat:: global proxy.process.net.connections_throttled_out integer
67+
:type: counter
68+
69+
.. ts:stat:: global proxy.process.net.max.active.connections_throttled_in integer
70+
:type: counter
71+
6372
.. ts:stat:: global proxy.process.net.default_inactivity_timeout_applied integer
73+
.. ts:stat:: global proxy.process.net.default_inactivity_timeout_count integer
6474
.. ts:stat:: global proxy.process.net.dynamic_keep_alive_timeout_in_count integer
6575
.. ts:stat:: global proxy.process.net.dynamic_keep_alive_timeout_in_total integer
6676
.. ts:stat:: global proxy.process.net.inactivity_cop_lock_acquire_failure integer

iocore/net/Net.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ register_net_stats()
102102
const std::pair<const char *, Net_Stats> non_persistent[] = {
103103
{"proxy.process.net.accepts_currently_open", net_accepts_currently_open_stat},
104104
{"proxy.process.net.connections_currently_open", net_connections_currently_open_stat},
105-
{"proxy.process.net.default_inactivity_timeout_applied", default_inactivity_timeout_stat},
105+
{"proxy.process.net.default_inactivity_timeout_applied", default_inactivity_timeout_applied_stat},
106+
{"proxy.process.net.default_inactivity_timeout_count", default_inactivity_timeout_count_stat},
106107
{"proxy.process.net.dynamic_keep_alive_timeout_in_count", keep_alive_queue_timeout_count_stat},
107108
{"proxy.process.net.dynamic_keep_alive_timeout_in_total", keep_alive_queue_timeout_total_stat},
108109
{"proxy.process.socks.connections_currently_open", socks_connections_currently_open_stat},
@@ -130,7 +131,8 @@ register_net_stats()
130131
NET_CLEAR_DYN_STAT(socks_connections_currently_open_stat);
131132
NET_CLEAR_DYN_STAT(keep_alive_queue_timeout_total_stat);
132133
NET_CLEAR_DYN_STAT(keep_alive_queue_timeout_count_stat);
133-
NET_CLEAR_DYN_STAT(default_inactivity_timeout_stat);
134+
NET_CLEAR_DYN_STAT(default_inactivity_timeout_count_stat);
135+
NET_CLEAR_DYN_STAT(default_inactivity_timeout_applied_stat);
134136

135137
RecRegisterRawStat(net_rsb, RECT_PROCESS, "proxy.process.tcp.total_accepts", RECD_INT, RECP_NON_PERSISTENT,
136138
static_cast<int>(net_tcp_accept_stat), RecRawStatSyncSum);
@@ -140,6 +142,8 @@ register_net_stats()
140142
(int)net_connections_throttled_in_stat, RecRawStatSyncSum);
141143
RecRegisterRawStat(net_rsb, RECT_PROCESS, "proxy.process.net.connections_throttled_out", RECD_INT, RECP_PERSISTENT,
142144
(int)net_connections_throttled_out_stat, RecRawStatSyncSum);
145+
RecRegisterRawStat(net_rsb, RECT_PROCESS, "proxy.process.net.max.active.connections_throttled_in", RECD_INT, RECP_PERSISTENT,
146+
(int)net_connections_max_active_throttled_in_stat, RecRawStatSyncSum);
143147
}
144148

145149
void

iocore/net/P_Net.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,14 @@ enum Net_Stats {
5151
inactivity_cop_lock_acquire_failure_stat,
5252
keep_alive_queue_timeout_total_stat,
5353
keep_alive_queue_timeout_count_stat,
54-
default_inactivity_timeout_stat,
54+
default_inactivity_timeout_applied_stat,
55+
default_inactivity_timeout_count_stat,
5556
net_fastopen_attempts_stat,
5657
net_fastopen_successes_stat,
5758
net_tcp_accept_stat,
5859
net_connections_throttled_in_stat,
5960
net_connections_throttled_out_stat,
61+
net_connections_max_active_throttled_in_stat,
6062
Net_Stat_Count
6163
};
6264

iocore/net/UnixNet.cc

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,25 @@ class InactivityCop : public Continuation
6969
continue;
7070
}
7171

72+
// set a default inactivity timeout if one is not set
73+
bool use_default_inactivity_timeout = false;
74+
if (ne->next_inactivity_timeout_at == 0 && nh.config.default_inactivity_timeout > 0) {
75+
Debug("inactivity_cop", "vc: %p inactivity timeout not set, setting a default of %d", ne,
76+
nh.config.default_inactivity_timeout);
77+
use_default_inactivity_timeout = true;
78+
ne->set_inactivity_timeout(HRTIME_SECONDS(nh.config.default_inactivity_timeout));
79+
NET_INCREMENT_DYN_STAT(default_inactivity_timeout_applied_stat);
80+
} else {
81+
Debug("inactivity_cop_verbose", "vc: %p now: %" PRId64 " timeout at: %" PRId64 " timeout in: %" PRId64, ne,
82+
ink_hrtime_to_sec(now), ink_hrtime_to_sec(ne->next_inactivity_timeout_at),
83+
ink_hrtime_to_sec(ne->inactivity_timeout_in));
84+
}
85+
7286
if (ne->next_inactivity_timeout_at && ne->next_inactivity_timeout_at < now) {
87+
if (use_default_inactivity_timeout) {
88+
// track the connections that timed out due to default inactivity
89+
NET_INCREMENT_DYN_STAT(default_inactivity_timeout_count_stat);
90+
}
7391
if (nh.keep_alive_queue.in(ne)) {
7492
// only stat if the connection is in keep-alive, there can be other inactivity timeouts
7593
ink_hrtime diff = (now - (ne->next_inactivity_timeout_at - ne->inactivity_timeout_in)) / HRTIME_SECOND;
@@ -721,16 +739,22 @@ NetHandler::add_to_active_queue(NetEvent *ne)
721739
max_connections_per_thread_in, active_queue_size, keep_alive_queue_size);
722740
ink_assert(mutex->thread_holding == this_ethread());
723741

742+
bool active_queue_full = false;
743+
724744
// if active queue is over size then close inactive connections
725745
if (manage_active_queue() == false) {
726-
// there is no room left in the queue
727-
return false;
746+
active_queue_full = true;
728747
}
729748

730749
if (active_queue.in(ne)) {
731750
// already in the active queue, move the head
732751
active_queue.remove(ne);
733752
} else {
753+
if (active_queue_full) {
754+
// there is no room left in the queue
755+
NET_SUM_DYN_STAT(net_connections_max_active_throttled_in_stat, 1);
756+
return false;
757+
}
734758
// in the keep-alive queue or no queue, new to this queue
735759
remove_from_keep_alive_queue(ne);
736760
++active_queue_size;

iocore/net/UnixNetVConnection.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,10 +1352,6 @@ TS_INLINE void
13521352
UnixNetVConnection::set_inactivity_timeout(ink_hrtime timeout_in)
13531353
{
13541354
Debug("socket", "Set inactive timeout=%" PRId64 ", for NetVC=%p", timeout_in, this);
1355-
if (timeout_in == 0) {
1356-
// set default inactivity timeout
1357-
timeout_in = HRTIME_SECONDS(nh->config.default_inactivity_timeout);
1358-
}
13591355
inactivity_timeout_in = timeout_in;
13601356
next_inactivity_timeout_at = Thread::get_hrtime() + inactivity_timeout_in;
13611357
}

proxy/http/Http1ClientSession.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,12 @@ Http1ClientSession::new_transaction()
465465
return;
466466
}
467467

468+
if (!client_vc->add_to_active_queue()) {
469+
// no room in the active queue close the connection
470+
this->do_io_close();
471+
return;
472+
}
473+
468474
// Defensive programming, make sure nothing persists across
469475
// connection re-use
470476
half_close = false;
@@ -474,7 +480,6 @@ Http1ClientSession::new_transaction()
474480
trans.set_proxy_ssn(this);
475481
transact_count++;
476482

477-
client_vc->add_to_active_queue();
478483
trans.new_transaction(read_from_early_data > 0 ? true : false);
479484
}
480485

proxy/http2/Http2ConnectionState.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,13 @@ Http2ConnectionState::state_closed(int event, void *edata)
11531153
Http2Stream *
11541154
Http2ConnectionState::create_stream(Http2StreamId new_id, Http2Error &error)
11551155
{
1156+
// first check if we've hit the active connection limit
1157+
if (!ua_session->get_netvc()->add_to_active_queue()) {
1158+
error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR,
1159+
"refused to create new stream, maxed out active connections");
1160+
return nullptr;
1161+
}
1162+
11561163
// In half_close state, TS doesn't create new stream. Because GOAWAY frame is sent to client
11571164
if (ua_session->get_half_close_local_flag()) {
11581165
error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
@@ -1226,7 +1233,6 @@ Http2ConnectionState::create_stream(Http2StreamId new_id, Http2Error &error)
12261233
new_stream->mutex = new_ProxyMutex();
12271234
new_stream->is_first_transaction_flag = get_stream_requests() == 0;
12281235
increment_stream_requests();
1229-
ua_session->get_netvc()->add_to_active_queue();
12301236

12311237
return new_stream;
12321238
}

0 commit comments

Comments
 (0)