Skip to content

Commit

Permalink
Refactor resource manager (envoyproxy#11182)
Browse files Browse the repository at this point in the history
This patch separates the Resource class from the resource manager implementation and allows for resource limit tracking in other parts of the code base.

Signed-off-by: Tony Allen <[email protected]>
  • Loading branch information
tonya11en committed Jun 8, 2020
1 parent ae87993 commit 9bfd872
Show file tree
Hide file tree
Showing 15 changed files with 253 additions and 87 deletions.
5 changes: 5 additions & 0 deletions include/envoy/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ envoy_cc_library(
hdrs = ["mutex_tracer.h"],
)

envoy_cc_library(
name = "resource_interface",
hdrs = ["resource.h"],
)

envoy_cc_library(
name = "time_interface",
hdrs = ["time.h"],
Expand Down
47 changes: 47 additions & 0 deletions include/envoy/common/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <cstdint>

#include "envoy/common/pure.h"

#pragma once

namespace Envoy {

/**
* A handle for use by any resource managers.
*/
class ResourceLimit {
public:
virtual ~ResourceLimit() = default;

/**
* @return true if the resource can be created.
*/
virtual bool canCreate() PURE;

/**
* Increment the resource count.
*/
virtual void inc() PURE;

/**
* Decrement the resource count.
*/
virtual void dec() PURE;

/**
* Decrement the resource count by a specific amount.
*/
virtual void decBy(uint64_t amount) PURE;

/**
* @return the current maximum allowed number of this resource.
*/
virtual uint64_t max() PURE;

/**
* @return the current resource count.
*/
virtual uint64_t count() const PURE;
};

} // namespace Envoy
1 change: 1 addition & 0 deletions include/envoy/network/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ envoy_cc_library(
":connection_interface",
":listen_socket_interface",
"//include/envoy/access_log:access_log_interface",
"//include/envoy/common:resource_interface",
"//include/envoy/stats:stats_interface",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
Expand Down
1 change: 1 addition & 0 deletions include/envoy/upstream/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ envoy_cc_library(
envoy_cc_library(
name = "resource_manager_interface",
hdrs = ["resource_manager.h"],
deps = ["//include/envoy/common:resource_interface"],
)

envoy_cc_library(
Expand Down
63 changes: 13 additions & 50 deletions include/envoy/upstream/resource_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <memory>

#include "envoy/common/pure.h"
#include "envoy/common/resource.h"

namespace Envoy {
namespace Upstream {
Expand All @@ -16,54 +17,16 @@ namespace Upstream {
enum class ResourcePriority { Default, High };
const size_t NumResourcePriorities = 2;

/**
* An individual resource tracked by the resource manager.
*/
class Resource {
public:
virtual ~Resource() = default;

/**
* @return true if the resource can be created.
*/
virtual bool canCreate() PURE;

/**
* Increment the resource count.
*/
virtual void inc() PURE;

/**
* Decrement the resource count.
*/
virtual void dec() PURE;

/**
* Decrement the resource count by a specific amount.
*/
virtual void decBy(uint64_t amount) PURE;

/**
* @return the current maximum allowed number of this resource.
*/
virtual uint64_t max() PURE;

/**
* @return the current resource count.
*/
virtual uint64_t count() const PURE;
};

/**
* RAII wrapper that increments a resource on construction and decrements it on destruction.
*/
class ResourceAutoIncDec {
public:
ResourceAutoIncDec(Resource& resource) : resource_(resource) { resource_.inc(); }
ResourceAutoIncDec(ResourceLimit& resource) : resource_(resource) { resource_.inc(); }
~ResourceAutoIncDec() { resource_.dec(); }

private:
Resource& resource_;
ResourceLimit& resource_;
};

using ResourceAutoIncDecPtr = std::unique_ptr<ResourceAutoIncDec>;
Expand All @@ -78,31 +41,31 @@ class ResourceManager {
virtual ~ResourceManager() = default;

/**
* @return Resource& active TCP connections and UDP sessions.
* @return ResourceLimit& active TCP connections and UDP sessions.
*/
virtual Resource& connections() PURE;
virtual ResourceLimit& connections() PURE;

/**
* @return Resource& active pending requests (requests that have not yet been attached to a
* @return ResourceLimit& active pending requests (requests that have not yet been attached to a
* connection pool connection).
*/
virtual Resource& pendingRequests() PURE;
virtual ResourceLimit& pendingRequests() PURE;

/**
* @return Resource& active requests (requests that are currently bound to a connection pool
* @return ResourceLimit& active requests (requests that are currently bound to a connection pool
* connection and are awaiting response).
*/
virtual Resource& requests() PURE;
virtual ResourceLimit& requests() PURE;

/**
* @return Resource& active retries.
* @return ResourceLimit& active retries.
*/
virtual Resource& retries() PURE;
virtual ResourceLimit& retries() PURE;

/**
* @return Resource& active connection pools.
* @return ResourceLimit& active connection pools.
*/
virtual Resource& connectionPools() PURE;
virtual ResourceLimit& connectionPools() PURE;
};

} // namespace Upstream
Expand Down
9 changes: 9 additions & 0 deletions source/common/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,15 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "basic_resource_lib",
hdrs = ["basic_resource_impl.h"],
deps = [
"//include/envoy/common:resource_interface",
"//include/envoy/runtime:runtime_interface",
],
)

envoy_cc_library(
name = "macros",
hdrs = ["macros.h"],
Expand Down
60 changes: 60 additions & 0 deletions source/common/common/basic_resource_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once

#include <limits>

#include "envoy/common/resource.h"
#include "envoy/runtime/runtime.h"

#include "common/common/assert.h"

#include "absl/types/optional.h"

namespace Envoy {

/**
* A handle to track some limited resource.
*
* NOTE:
* This implementation makes some assumptions which favor simplicity over correctness. Though
* atomics are used, it is possible for resources to temporarily go above the supplied maximums.
* This should not effect overall behavior.
*/
class BasicResourceLimitImpl : public ResourceLimit {
public:
BasicResourceLimitImpl(uint64_t max, Runtime::Loader& runtime, const std::string& runtime_key)
: max_(max), runtime_(&runtime), runtime_key_(runtime_key) {}
BasicResourceLimitImpl(uint64_t max) : max_(max), runtime_(nullptr) {}
BasicResourceLimitImpl() : max_(std::numeric_limits<uint64_t>::max()), runtime_(nullptr) {}

bool canCreate() override { return current_.load() < max(); }

void inc() override { ++current_; }

void dec() override { decBy(1); }

void decBy(uint64_t amount) override {
ASSERT(current_ >= amount);
current_ -= amount;
}

uint64_t max() override {
return (runtime_ != nullptr && runtime_key_.has_value())
? runtime_->snapshot().getInteger(runtime_key_.value(), max_)
: max_;
}

uint64_t count() const override { return current_.load(); }

void setMax(uint64_t new_max) { max_ = new_max; }
void resetMax() { max_ = std::numeric_limits<uint64_t>::max(); }

protected:
std::atomic<uint64_t> current_{};

private:
uint64_t max_;
Runtime::Loader* runtime_{nullptr};
const absl::optional<std::string> runtime_key_;
};

} // namespace Envoy
1 change: 1 addition & 0 deletions source/common/upstream/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ envoy_cc_library(
"//include/envoy/upstream:resource_manager_interface",
"//include/envoy/upstream:upstream_interface",
"//source/common/common:assert_lib",
"//source/common/common:basic_resource_lib",
],
)

Expand Down
2 changes: 1 addition & 1 deletion source/common/upstream/conn_pool_map_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ ConnPoolMap<KEY_TYPE, POOL_TYPE>::getPool(KEY_TYPE key, const PoolFactory& facto
if (pool_iter != active_pools_.end()) {
return std::ref(*(pool_iter->second));
}
Resource& connPoolResource = host_->cluster().resourceManager(priority_).connectionPools();
ResourceLimit& connPoolResource = host_->cluster().resourceManager(priority_).connectionPools();
// We need a new pool. Check if we have room.
if (!connPoolResource.canCreate()) {
// We're full. Try to free up a pool. If we can't, bail out.
Expand Down
Loading

0 comments on commit 9bfd872

Please sign in to comment.