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
5 changes: 5 additions & 0 deletions include/envoy/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ envoy_basic_cc_library(
include_prefix = "envoy/common",
)

envoy_cc_library(
name = "conn_pool_interface",
hdrs = ["conn_pool.h"],
)

envoy_cc_library(
name = "mutex_tracer",
hdrs = ["mutex_tracer.h"],
Expand Down
18 changes: 18 additions & 0 deletions include/envoy/common/conn_pool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

namespace Envoy {
namespace ConnectionPool {

enum class PoolFailureReason {
// A resource overflowed and policy prevented a new connection from being created.
Overflow,
// A local connection failure took place while creating a new connection.
LocalConnectionFailure,
// A remote connection failure took place while creating a new connection.
RemoteConnectionFailure,
// A timeout occurred while creating a new connection.
Timeout,
};

} // namespace ConnectionPool
} // namespace Envoy
1 change: 1 addition & 0 deletions include/envoy/http/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ envoy_cc_library(
hdrs = ["conn_pool.h"],
deps = [
":codec_interface",
"//include/envoy/common:conn_pool_interface",
"//include/envoy/event:deferred_deletable",
"//include/envoy/upstream:upstream_interface",
],
Expand Down
11 changes: 2 additions & 9 deletions include/envoy/http/conn_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <functional>
#include <memory>

#include "envoy/common/conn_pool.h"
#include "envoy/common/pure.h"
#include "envoy/event/deferred_deletable.h"
#include "envoy/http/codec.h"
Expand All @@ -25,15 +26,7 @@ class Cancellable {
virtual void cancel() PURE;
};

/**
* Reason that a pool stream could not be obtained.
*/
enum class PoolFailureReason {
// A resource overflowed and policy prevented a new stream from being created.
Overflow,
// A connection failure took place and the stream could not be bound.
ConnectionFailure
};
using PoolFailureReason = ::Envoy::ConnectionPool::PoolFailureReason;

/**
* Pool callbacks invoked in the context of a newStream() call, either synchronously or
Expand Down
1 change: 1 addition & 0 deletions include/envoy/tcp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ envoy_cc_library(
hdrs = ["conn_pool.h"],
deps = [
"//include/envoy/buffer:buffer_interface",
"//include/envoy/common:conn_pool_interface",
"//include/envoy/event:deferred_deletable",
"//include/envoy/upstream:upstream_interface",
],
Expand Down
16 changes: 2 additions & 14 deletions include/envoy/tcp/conn_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <memory>

#include "envoy/buffer/buffer.h"
#include "envoy/common/conn_pool.h"
#include "envoy/common/pure.h"
#include "envoy/event/deferred_deletable.h"
#include "envoy/upstream/upstream.h"
Expand Down Expand Up @@ -42,20 +43,6 @@ class Cancellable {
virtual void cancel(CancelPolicy cancel_policy) PURE;
};

/**
* Reason that a pool connection could not be obtained.
*/
enum class PoolFailureReason {
// A resource overflowed and policy prevented a new connection from being created.
Overflow,
// A local connection failure took place while creating a new connection.
LocalConnectionFailure,
// A remote connection failure took place while creating a new connection.
RemoteConnectionFailure,
// A timeout occurred while creating a new connection.
Timeout,
};

/*
* UpstreamCallbacks for connection pool upstream connection callbacks and data. Note that
* onEvent(Connected) is never triggered since the event always occurs before a ConnectionPool
Expand Down Expand Up @@ -131,6 +118,7 @@ class ConnectionData {
};

using ConnectionDataPtr = std::unique_ptr<ConnectionData>;
using PoolFailureReason = ::Envoy::ConnectionPool::PoolFailureReason;

/**
* Pool callbacks invoked in the context of a newConnection() call, either synchronously or
Expand Down
17 changes: 13 additions & 4 deletions source/common/http/conn_pool_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,23 @@ void ConnPoolImplBase::onConnectionEvent(ConnPoolImplBase::ActiveClient& client,
host_->cluster().stats().upstream_cx_connect_fail_.inc();
host_->stats().cx_connect_fail_.inc();

ConnectionPool::PoolFailureReason reason;
if (client.timed_out_) {
reason = ConnectionPool::PoolFailureReason::Timeout;
} else if (event == Network::ConnectionEvent::RemoteClose) {
reason = ConnectionPool::PoolFailureReason::RemoteConnectionFailure;
} else {
reason = ConnectionPool::PoolFailureReason::LocalConnectionFailure;
}

// Raw connect failures should never happen under normal circumstances. If we have an upstream
// that is behaving badly, requests can get stuck here in the pending state. If we see a
// connect failure, we purge all pending requests so that calling code can determine what to
// do with the request.
// NOTE: We move the existing pending requests to a temporary list. This is done so that
// if retry logic submits a new request to the pool, we don't fail it inline.
purgePendingRequests(client.real_host_description_,
client.codec_client_->connectionFailureReason());
client.codec_client_->connectionFailureReason(), reason);
}

// We need to release our resourceManager() resources before checking below for
Expand Down Expand Up @@ -342,16 +351,15 @@ ConnPoolImplBase::newPendingRequest(ResponseDecoder& decoder,

void ConnPoolImplBase::purgePendingRequests(
const Upstream::HostDescriptionConstSharedPtr& host_description,
absl::string_view failure_reason) {
absl::string_view failure_reason, ConnectionPool::PoolFailureReason reason) {
// NOTE: We move the existing pending requests to a temporary list. This is done so that
// if retry logic submits a new request to the pool, we don't fail it inline.
pending_requests_to_purge_ = std::move(pending_requests_);
while (!pending_requests_to_purge_.empty()) {
PendingRequestPtr request =
pending_requests_to_purge_.front()->removeFromList(pending_requests_to_purge_);
host_->cluster().stats().upstream_rq_pending_failure_eject_.inc();
request->callbacks_.onPoolFailure(ConnectionPool::PoolFailureReason::ConnectionFailure,
failure_reason, host_description);
request->callbacks_.onPoolFailure(reason, failure_reason, host_description);
}
}

Expand Down Expand Up @@ -428,6 +436,7 @@ void ConnPoolImplBase::ActiveClient::releaseResources() {
void ConnPoolImplBase::ActiveClient::onConnectTimeout() {
ENVOY_CONN_LOG(debug, "connect timeout", *codec_client_);
parent_.host_->cluster().stats().upstream_cx_connect_timeout_.inc();
timed_out_ = true;
close();
}

Expand Down
4 changes: 3 additions & 1 deletion source/common/http/conn_pool_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class ConnPoolImplBase : public ConnectionPool::Instance,
Stats::TimespanPtr conn_length_;
Event::TimerPtr connect_timer_;
bool resources_released_{false};
bool timed_out_{false};
};

using ActiveClientPtr = std::unique_ptr<ActiveClient>;
Expand Down Expand Up @@ -126,7 +127,8 @@ class ConnPoolImplBase : public ConnectionPool::Instance,

// Fails all pending requests, calling onPoolFailure on the associated callbacks.
void purgePendingRequests(const Upstream::HostDescriptionConstSharedPtr& host_description,
absl::string_view failure_reason);
absl::string_view failure_reason,
ConnectionPool::PoolFailureReason pool_failure_reason);

// Closes any idle connections.
void closeIdleConnections();
Expand Down
8 changes: 5 additions & 3 deletions source/common/http/conn_pool_base_legacy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,18 @@ ConnPoolImplBase::newPendingRequest(ResponseDecoder& decoder,

void ConnPoolImplBase::purgePendingRequests(
const Upstream::HostDescriptionConstSharedPtr& host_description,
absl::string_view failure_reason) {
absl::string_view failure_reason, bool was_remote_close) {
// NOTE: We move the existing pending requests to a temporary list. This is done so that
// if retry logic submits a new request to the pool, we don't fail it inline.
pending_requests_to_purge_ = std::move(pending_requests_);
while (!pending_requests_to_purge_.empty()) {
PendingRequestPtr request =
pending_requests_to_purge_.front()->removeFromList(pending_requests_to_purge_);
host_->cluster().stats().upstream_rq_pending_failure_eject_.inc();
request->callbacks_.onPoolFailure(ConnectionPool::PoolFailureReason::ConnectionFailure,
failure_reason, host_description);
request->callbacks_.onPoolFailure(
was_remote_close ? ConnectionPool::PoolFailureReason::RemoteConnectionFailure
: ConnectionPool::PoolFailureReason::LocalConnectionFailure,
failure_reason, host_description);
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/common/http/conn_pool_base_legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class ConnPoolImplBase : protected Logger::Loggable<Logger::Id::pool> {

// Fails all pending requests, calling onPoolFailure on the associated callbacks.
void purgePendingRequests(const Upstream::HostDescriptionConstSharedPtr& host_description,
absl::string_view failure_reason);
absl::string_view failure_reason, bool was_remote);

// Must be implemented by sub class. Attempts to drain inactive clients.
virtual void checkForDrained() PURE;
Expand Down
3 changes: 2 additions & 1 deletion source/common/http/http1/conn_pool_legacy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ void ConnPoolImpl::onConnectionEvent(ActiveClient& client, Network::ConnectionEv
ENVOY_CONN_LOG(debug, "purge pending, failure reason: {}", *client.codec_client_,
client.codec_client_->connectionFailureReason());
purgePendingRequests(client.real_host_description_,
client.codec_client_->connectionFailureReason());
client.codec_client_->connectionFailureReason(),
event == Network::ConnectionEvent::RemoteClose);
}

dispatcher_.deferredDelete(std::move(removed));
Expand Down
4 changes: 2 additions & 2 deletions source/common/http/http2/conn_pool_legacy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ void ConnPoolImpl::onConnectionEvent(ActiveClient& client, Network::ConnectionEv
// do with the request.
// NOTE: We move the existing pending requests to a temporary list. This is done so that
// if retry logic submits a new request to the pool, we don't fail it inline.
purgePendingRequests(client.real_host_description_,
client.client_->connectionFailureReason());
purgePendingRequests(client.real_host_description_, client.client_->connectionFailureReason(),
event == Network::ConnectionEvent::RemoteClose);
}

if (&client == primary_client_.get()) {
Expand Down
12 changes: 8 additions & 4 deletions source/common/router/upstream_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -289,17 +289,21 @@ void UpstreamRequest::onPerTryTimeout() {
}
}

void UpstreamRequest::onPoolFailure(Http::ConnectionPool::PoolFailureReason reason,
void UpstreamRequest::onPoolFailure(ConnectionPool::PoolFailureReason reason,
absl::string_view transport_failure_reason,
Upstream::HostDescriptionConstSharedPtr host) {
Http::StreamResetReason reset_reason = Http::StreamResetReason::ConnectionFailure;
switch (reason) {
case Http::ConnectionPool::PoolFailureReason::Overflow:
case ConnectionPool::PoolFailureReason::Overflow:
reset_reason = Http::StreamResetReason::Overflow;
break;
case Http::ConnectionPool::PoolFailureReason::ConnectionFailure:
case ConnectionPool::PoolFailureReason::RemoteConnectionFailure:
FALLTHRU;
case ConnectionPool::PoolFailureReason::LocalConnectionFailure:
reset_reason = Http::StreamResetReason::ConnectionFailure;
break;
case ConnectionPool::PoolFailureReason::Timeout:
reset_reason = Http::StreamResetReason::LocalReset;
}

// Mimic an upstream reset.
Expand Down Expand Up @@ -485,7 +489,7 @@ bool HttpConnPool::cancelAnyPendingRequest() {

absl::optional<Http::Protocol> HttpConnPool::protocol() const { return conn_pool_.protocol(); }

void HttpConnPool::onPoolFailure(Http::ConnectionPool::PoolFailureReason reason,
void HttpConnPool::onPoolFailure(ConnectionPool::PoolFailureReason reason,
absl::string_view transport_failure_reason,
Upstream::HostDescriptionConstSharedPtr host) {
callbacks_->onPoolFailure(reason, transport_failure_reason, host);
Expand Down
6 changes: 3 additions & 3 deletions source/common/router/upstream_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class GenericConnectionPoolCallbacks {
public:
virtual ~GenericConnectionPoolCallbacks() = default;

virtual void onPoolFailure(Http::ConnectionPool::PoolFailureReason reason,
virtual void onPoolFailure(ConnectionPool::PoolFailureReason reason,
absl::string_view transport_failure_reason,
Upstream::HostDescriptionConstSharedPtr host) PURE;
virtual void onPoolReady(std::unique_ptr<GenericUpstream>&& upstream,
Expand Down Expand Up @@ -97,7 +97,7 @@ class UpstreamRequest : public Logger::Loggable<Logger::Id::router>,
void enableDataFromDownstreamForFlowControl();

// GenericConnPool
void onPoolFailure(Http::ConnectionPool::PoolFailureReason reason,
void onPoolFailure(ConnectionPool::PoolFailureReason reason,
absl::string_view transport_failure_reason,
Upstream::HostDescriptionConstSharedPtr host) override;
void onPoolReady(std::unique_ptr<GenericUpstream>&& upstream,
Expand Down Expand Up @@ -186,7 +186,7 @@ class HttpConnPool : public GenericConnPool, public Http::ConnectionPool::Callba
absl::optional<Http::Protocol> protocol() const override;

// Http::ConnectionPool::Callbacks
void onPoolFailure(Http::ConnectionPool::PoolFailureReason reason,
void onPoolFailure(ConnectionPool::PoolFailureReason reason,
absl::string_view transport_failure_reason,
Upstream::HostDescriptionConstSharedPtr host) override;
void onPoolReady(Http::RequestEncoder& callbacks_encoder,
Expand Down
29 changes: 7 additions & 22 deletions source/common/tcp_proxy/tcp_proxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,6 @@

namespace Envoy {
namespace TcpProxy {
namespace {

Tcp::ConnectionPool::PoolFailureReason
httpToTcpFailure(Http::ConnectionPool::PoolFailureReason reason) {
switch (reason) {
case Http::ConnectionPool::PoolFailureReason::Overflow:
return Tcp::ConnectionPool::PoolFailureReason::Overflow;
case Http::ConnectionPool::PoolFailureReason::ConnectionFailure:
// TODO(alyssawilk) It's unclear which this is.
return Tcp::ConnectionPool::PoolFailureReason::LocalConnectionFailure;
}
return Tcp::ConnectionPool::PoolFailureReason::LocalConnectionFailure;
}

} // namespace

const std::string& PerConnectionCluster::key() {
CONSTRUCT_ON_FIRST_USE(std::string, "envoy.tcp_proxy.cluster");
Expand Down Expand Up @@ -464,24 +449,24 @@ Network::FilterStatus Filter::initializeUpstreamConnection() {
return Network::FilterStatus::StopIteration;
}

void Filter::onPoolFailure(Tcp::ConnectionPool::PoolFailureReason reason,
void Filter::onPoolFailure(ConnectionPool::PoolFailureReason reason,
Upstream::HostDescriptionConstSharedPtr host) {
upstream_handle_.reset();

read_callbacks_->upstreamHost(host);
getStreamInfo().onUpstreamHostSelected(host);

switch (reason) {
case Tcp::ConnectionPool::PoolFailureReason::Overflow:
case Tcp::ConnectionPool::PoolFailureReason::LocalConnectionFailure:
case ConnectionPool::PoolFailureReason::Overflow:
case ConnectionPool::PoolFailureReason::LocalConnectionFailure:
upstream_callbacks_->onEvent(Network::ConnectionEvent::LocalClose);
break;

case Tcp::ConnectionPool::PoolFailureReason::RemoteConnectionFailure:
case ConnectionPool::PoolFailureReason::RemoteConnectionFailure:
upstream_callbacks_->onEvent(Network::ConnectionEvent::RemoteClose);
break;

case Tcp::ConnectionPool::PoolFailureReason::Timeout:
case ConnectionPool::PoolFailureReason::Timeout:
onConnectTimeout();
break;

Expand Down Expand Up @@ -514,9 +499,9 @@ void Filter::onPoolReady(Tcp::ConnectionPool::ConnectionDataPtr&& conn_data,
latched_data->connection().streamInfo().filterState());
}

void Filter::onPoolFailure(Http::ConnectionPool::PoolFailureReason failure, absl::string_view,
void Filter::onPoolFailure(ConnectionPool::PoolFailureReason failure, absl::string_view,
Upstream::HostDescriptionConstSharedPtr host) {
onPoolFailure(httpToTcpFailure(failure), host);
onPoolFailure(failure, host);
}

void Filter::onPoolReady(Http::RequestEncoder& request_encoder,
Expand Down
4 changes: 2 additions & 2 deletions source/common/tcp_proxy/tcp_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,13 @@ class Filter : public Network::ReadFilter,
void initializeReadFilterCallbacks(Network::ReadFilterCallbacks& callbacks) override;

// Tcp::ConnectionPool::Callbacks
void onPoolFailure(Tcp::ConnectionPool::PoolFailureReason reason,
void onPoolFailure(ConnectionPool::PoolFailureReason reason,
Upstream::HostDescriptionConstSharedPtr host) override;
void onPoolReady(Tcp::ConnectionPool::ConnectionDataPtr&& conn_data,
Upstream::HostDescriptionConstSharedPtr host) override;

// Http::ConnectionPool::Callbacks,
void onPoolFailure(Http::ConnectionPool::PoolFailureReason reason,
void onPoolFailure(ConnectionPool::PoolFailureReason reason,
absl::string_view transport_failure_reason,
Upstream::HostDescriptionConstSharedPtr host) override;
void onPoolReady(Http::RequestEncoder& request_encoder,
Expand Down
Loading