Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

conn_pool: unifying status codes #10854

Merged
merged 2 commits into from
Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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_{true};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be initialized false? (I don't see anything that clears, so I think every failure in onConnectionEvent will report a time out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gack, that was not supposed to be part of the commit. That's the ASSERT-fail moral equivalent of "surely tests will fail if I set this wrong" which they surprisingly didn't. And now we have tests that will fail :-)

};

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