Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 1 addition & 27 deletions doc/admin-guide/files/records.config.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1475,15 +1475,9 @@ Origin Server Connect Attempts

Set a limit for the number of concurrent connections to an upstream server group. A value of
``0`` disables checking. If a transaction attempts to connect to a group which already has the
maximum number of concurrent connections the transaction either rechecks after a delay or a 503
maximum number of concurrent connections a 503
(``HTTP_STATUS_SERVICE_UNAVAILABLE``) error response is sent to the user agent. To configure

Number of transactions that can be delayed concurrently
See :ts:cv:`proxy.config.http.per_server.connection.queue_size`.

How long to delay before rechecking
See :ts:cv:`proxy.config.http.per_server.connection.queue_delay`.

Upstream server group definition
See :ts:cv:`proxy.config.http.per_server.connection.match`.

Expand Down Expand Up @@ -1517,26 +1511,6 @@ Origin Server Connect Attempts
This setting is independent of the :ts:cv:`setting for upstream session sharing matching
<proxy.config.http.server_session_sharing.match>`.

.. ts:cv:: CONFIG proxy.config.http.per_server.connection.queue_size INT 0
:reloadable:

Controls the number of transactions that can be waiting on an upstream server group.

``-1``
Unlimited.

``0``
Never wait. If the connection maximum has been reached immediately respond with an error.

A positive number
If there are less than this many waiting transactions, delay this transaction and try again. Otherwise respond immediately with an error.

.. ts:cv:: CONFIG proxy.config.http.per_server.connection.queue_delay INT 100
:reloadable:
:units: milliseconds

If a transaction is delayed due to too many connections in an upstream server group, delay this amount of time before checking again.

.. ts:cv:: CONFIG proxy.config.http.per_server.connection.alert_delay INT 60
:reloadable:
:units: seconds
Expand Down
4 changes: 0 additions & 4 deletions mgmt/RecordsConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,6 @@ static const RecordElement RecordsConfig[] =
,
{RECT_CONFIG, "proxy.config.http.per_server.connection.alert_delay", RECD_INT, "60", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
,
{RECT_CONFIG, "proxy.config.http.per_server.connection.queue_size", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL}
,
{RECT_CONFIG, "proxy.config.http.per_server.connection.queue_delay", RECD_INT, "100", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL}
,
{RECT_CONFIG, "proxy.config.http.per_server.connection.min", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
,
{RECT_CONFIG, "proxy.config.http.attach_server_session_to_client", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
Expand Down
14 changes: 3 additions & 11 deletions proxy/http/HttpConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1391,17 +1391,9 @@ HttpConfig::reconfigure()
params->disable_ssl_parenting = INT_TO_BOOL(m_master.disable_ssl_parenting);
params->oride.forward_connect_method = INT_TO_BOOL(m_master.oride.forward_connect_method);

params->server_max_connections = m_master.server_max_connections;
params->max_websocket_connections = m_master.max_websocket_connections;
params->oride.outbound_conntrack = m_master.oride.outbound_conntrack;
// If queuing for outbound connection tracking is enabled without enabling max connections, it is meaningless, so we'll warn
if (params->outbound_conntrack.queue_size > 0 &&
!(params->oride.outbound_conntrack.max > 0 || params->oride.outbound_conntrack.min > 0)) {
Warning("'%s' is set, but neither '%s' nor '%s' are "
"set, please correct your %s",
OutboundConnTrack::CONFIG_VAR_QUEUE_SIZE.data(), OutboundConnTrack::CONFIG_VAR_MAX.data(),
OutboundConnTrack::CONFIG_VAR_MIN.data(), ts::filename::RECORDS);
}
params->server_max_connections = m_master.server_max_connections;
params->max_websocket_connections = m_master.max_websocket_connections;
params->oride.outbound_conntrack = m_master.oride.outbound_conntrack;
params->oride.attach_server_session_to_client = m_master.oride.attach_server_session_to_client;

params->http_request_line_max_size = m_master.http_request_line_max_size;
Expand Down
59 changes: 15 additions & 44 deletions proxy/http/HttpConnectionCount.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,30 +104,6 @@ Config_Update_Conntrack_Max(const char *name, RecDataT dtype, RecData data, void
return false;
}

bool
Config_Update_Conntrack_Queue_Size(const char *name, RecDataT dtype, RecData data, void *cookie)
{
auto config = static_cast<OutboundConnTrack::GlobalConfig *>(cookie);

if (RECD_INT == dtype) {
config->queue_size = data.rec_int;
return true;
}
return false;
}

bool
Config_Update_Conntrack_Queue_Delay(const char *name, RecDataT dtype, RecData data, void *cookie)
{
auto config = static_cast<OutboundConnTrack::GlobalConfig *>(cookie);

if (RECD_INT == dtype && data.rec_int > 0) {
config->queue_delay = std::chrono::milliseconds(data.rec_int);
return true;
}
return false;
}

bool
Config_Update_Conntrack_Match(const char *name, RecDataT dtype, RecData data, void *cookie)
{
Expand Down Expand Up @@ -171,8 +147,6 @@ OutboundConnTrack::config_init(GlobalConfig *global, TxnConfig *txn)
Enable_Config_Var(CONFIG_VAR_MIN, &Config_Update_Conntrack_Min, txn);
Enable_Config_Var(CONFIG_VAR_MAX, &Config_Update_Conntrack_Max, txn);
Enable_Config_Var(CONFIG_VAR_MATCH, &Config_Update_Conntrack_Match, txn);
Enable_Config_Var(CONFIG_VAR_QUEUE_SIZE, &Config_Update_Conntrack_Queue_Size, global);
Enable_Config_Var(CONFIG_VAR_QUEUE_DELAY, &Config_Update_Conntrack_Queue_Delay, global);
Enable_Config_Var(CONFIG_VAR_ALERT_DELAY, &Config_Update_Conntrack_Alert_Delay, global);
}

Expand Down Expand Up @@ -269,13 +243,13 @@ OutboundConnTrack::to_json_string()
static const ts::BWFormat header_fmt{R"({{"count": {}, "list": [
)"};
static const ts::BWFormat item_fmt{
R"( {{"type": "{}", "ip": "{}", "fqdn": "{}", "current": {}, "max": {}, "blocked": {}, "queued": {}, "alert": {}}},
R"( {{"type": "{}", "ip": "{}", "fqdn": "{}", "current": {}, "max": {}, "blocked": {}, "alert": {}}},
)"};
static const std::string_view trailer{" \n]}"};

static const auto printer = [](ts::BufferWriter &w, Group const *g) -> ts::BufferWriter & {
w.print(item_fmt, g->_match_type, g->_addr, g->_fqdn, g->_count.load(), g->_count_max.load(), g->_blocked.load(),
g->_rescheduled.load(), g->get_last_alert_epoch_time());
g->get_last_alert_epoch_time());
return w;
};

Expand Down Expand Up @@ -310,18 +284,17 @@ OutboundConnTrack::dump(FILE *f)
self_type::get(groups);

if (groups.size()) {
fprintf(f, "\nUpstream Connection Tracking\n%7s | %5s | %10s | %24s | %33s | %8s |\n", "Current", "Block", "Queue", "Address",
"Hostname Hash", "Match");
fprintf(f, "------|-------|---------|--------------------------|-----------------------------------|----------|\n");
fprintf(f, "\nUpstream Connection Tracking\n%7s | %5s | %24s | %33s | %8s |\n", "Current", "Block", "Address", "Hostname Hash",
"Match");
fprintf(f, "------|-------|--------------------------|-----------------------------------|----------|\n");

for (Group const *g : groups) {
ts::LocalBufferWriter<128> w;
w.print("{:7} | {:5} | {:5} | {:24} | {:33} | {:8} |\n", g->_count.load(), g->_blocked.load(), g->_rescheduled.load(),
g->_addr, g->_hash, g->_match_type);
w.print("{:7} | {:5} | {:24} | {:33} | {:8} |\n", g->_count.load(), g->_blocked.load(), g->_addr, g->_hash, g->_match_type);
fwrite(w.data(), w.size(), 1, f);
}

fprintf(f, "------|-------|-------|--------------------------|-----------------------------------|----------|\n");
fprintf(f, "------|-------|--------------------------|-----------------------------------|----------|\n");
}
}

Expand Down Expand Up @@ -376,12 +349,11 @@ OutboundConnTrack::TxnState::Note_Unblocked(const TxnConfig *config, int count,
{
time_t lat; // last alert time (epoch seconds)

if ((_g->_blocked > 0 || _g->_rescheduled > 0) && _g->should_alert(&lat)) {
auto blocked = _g->_blocked.exchange(0);
auto rescheduled = _g->_rescheduled.exchange(0);
if (_g->_blocked > 0 && _g->should_alert(&lat)) {
auto blocked = _g->_blocked.exchange(0);
ts::LocalBufferWriter<256> w;
w.print("upstream unblocked: [{}] count={} limit={} group=({}) blocked={} queued={} upstream={}\0",
ts::bwf::Date(lat, "%b %d %H:%M:%S"sv), count, config->max, *_g, blocked, rescheduled, addr);
w.print("upstream unblocked: [{}] count={} limit={} group=({}) blocked={} upstream={}\0",
ts::bwf::Date(lat, "%b %d %H:%M:%S"sv), count, config->max, *_g, blocked, addr);
Debug(DEBUG_TAG, "%s", w.data());
Note("%s", w.data());
}
Expand All @@ -391,14 +363,13 @@ void
OutboundConnTrack::TxnState::Warn_Blocked(const TxnConfig *config, int64_t sm_id, int count, sockaddr const *addr,
char const *debug_tag)
{
bool alert_p = _g->should_alert();
auto blocked = alert_p ? _g->_blocked.exchange(0) : _g->_blocked.load();
auto rescheduled = alert_p ? _g->_rescheduled.exchange(0) : _g->_rescheduled.load();
bool alert_p = _g->should_alert();
auto blocked = alert_p ? _g->_blocked.exchange(0) : _g->_blocked.load();

if (alert_p || debug_tag) {
ts::LocalBufferWriter<256> w;
w.print("[{}] too many connections: count={} limit={} group=({}) blocked={} queued={} upstream={}\0", sm_id, count, config->max,
*_g, blocked, rescheduled, addr);
w.print("[{}] too many connections: count={} limit={} group=({}) blocked={} upstream={}\0", sm_id, count, config->max, *_g,
blocked, addr);

if (debug_tag) {
Debug(debug_tag, "%s", w.data());
Expand Down
15 changes: 1 addition & 14 deletions proxy/http/HttpConnectionCount.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ class OutboundConnTrack

/** Static configuration values. */
struct GlobalConfig {
int queue_size{0}; ///< Maximum delayed transactions.
std::chrono::milliseconds queue_delay{100}; ///< Reschedule / queue delay in ms.
std::chrono::seconds alert_delay{60}; ///< Alert delay in seconds.
std::chrono::seconds alert_delay{60}; ///< Alert delay in seconds.
};

// The names of the configuration values.
Expand All @@ -88,8 +86,6 @@ class OutboundConnTrack
static constexpr std::string_view CONFIG_VAR_MAX{"proxy.config.http.per_server.connection.max"_sv};
static constexpr std::string_view CONFIG_VAR_MIN{"proxy.config.http.per_server.connection.min"_sv};
static constexpr std::string_view CONFIG_VAR_MATCH{"proxy.config.http.per_server.connection.match"_sv};
static constexpr std::string_view CONFIG_VAR_QUEUE_SIZE{"proxy.config.http.per_server.connection.queue_size"_sv};
static constexpr std::string_view CONFIG_VAR_QUEUE_DELAY{"proxy.config.http.per_server.connection.queue_delay"_sv};
static constexpr std::string_view CONFIG_VAR_ALERT_DELAY{"proxy.config.http.per_server.connection.alert_delay"_sv};

/// A record for the outbound connection count.
Expand Down Expand Up @@ -122,7 +118,6 @@ class OutboundConnTrack
std::atomic<int> _count{0}; ///< Number of outbound connections.
std::atomic<int> _count_max{0}; ///< largest observed @a count value.
std::atomic<int> _blocked{0}; ///< Number of outbound connections blocked since last alert.
std::atomic<int> _rescheduled{0}; ///< # of connection reschedules.
std::atomic<int> _in_queue{0}; ///< # of connections queued, waiting for a connection.
std::atomic<Ticker> _last_alert{0}; ///< Absolute time of the last alert.

Expand Down Expand Up @@ -168,8 +163,6 @@ class OutboundConnTrack
void dequeue();
/// Note blocking a transaction.
void blocked();
/// Note a rescheduling
void rescheduled();
/// Clear all reservations.
void clear();
/// Drop the reservation - assume it will be cleaned up elsewhere.
Expand Down Expand Up @@ -392,12 +385,6 @@ OutboundConnTrack::TxnState::blocked()
++_g->_blocked;
}

inline void
OutboundConnTrack::TxnState::rescheduled()
{
++_g->_rescheduled;
}

/* === Linkage === */
inline auto
OutboundConnTrack::Linkage::next_ptr(value_type *value) -> value_type *&
Expand Down
27 changes: 3 additions & 24 deletions proxy/http/HttpSM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5088,30 +5088,9 @@ HttpSM::do_http_server_open(bool raw)

ink_assert(pending_action == nullptr); // in case of reschedule must not have already pending.

// If the queue is disabled, reschedule.
if (t_state.http_config_param->outbound_conntrack.queue_size < 0) {
ct_state.enqueue();
ct_state.rescheduled();
pending_action =
eventProcessor.schedule_in(this, HRTIME_MSECONDS(t_state.http_config_param->outbound_conntrack.queue_delay.count()));
} else if (t_state.http_config_param->outbound_conntrack.queue_size > 0) { // queue enabled, check for a slot
auto wcount = ct_state.enqueue();
if (wcount < t_state.http_config_param->outbound_conntrack.queue_size) {
ct_state.rescheduled();
SMDebug("http", "%s", lbw().print("[{}] queued for {}\0", sm_id, t_state.current.server->dst_addr).data());
pending_action =
eventProcessor.schedule_in(this, HRTIME_MSECONDS(t_state.http_config_param->outbound_conntrack.queue_delay.count()));
} else { // the queue is full
ct_state.dequeue(); // release the queue slot
ct_state.blocked(); // note the blockage.
HTTP_INCREMENT_DYN_STAT(http_origin_connections_throttled_stat);
send_origin_throttled_response();
}
} else { // queue size is 0, always block.
ct_state.blocked();
HTTP_INCREMENT_DYN_STAT(http_origin_connections_throttled_stat);
send_origin_throttled_response();
}
ct_state.blocked();
HTTP_INCREMENT_DYN_STAT(http_origin_connections_throttled_stat);
send_origin_throttled_response();

ct_state.Warn_Blocked(&t_state.txn_conf->outbound_conntrack, sm_id, ccount - 1, &t_state.current.server->dst_addr.sa,
debug_on && is_debug_tag_set("http") ? "http" : nullptr);
Expand Down