-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Cluster lazy loading #2740
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
Cluster lazy loading #2740
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,11 +17,21 @@ | |
| #include "envoy/runtime/runtime.h" | ||
| #include "envoy/upstream/load_balancer.h" | ||
| #include "envoy/upstream/thread_local_cluster.h" | ||
| #include "envoy/upstream/lazy_loader.h" | ||
| #include "envoy/upstream/upstream.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Upstream { | ||
|
|
||
| class ClusterUpdateCallbacks { | ||
| public: | ||
| virtual ~ClusterUpdateCallbacks() {} | ||
|
|
||
| virtual void onClusterAddOrUpdate(const ThreadLocalCluster& cluster) PURE; | ||
|
|
||
| virtual void onClusterRemoval(const std::string& cluster_name) PURE; | ||
| }; | ||
|
|
||
| /** | ||
| * Manages connection pools and load balancing for upstream clusters. The cluster manager is | ||
| * persistent and shared among multiple ongoing requests/connections. | ||
|
|
@@ -147,6 +157,11 @@ class ClusterManager { | |
| * @return std::string the local cluster name, or "" if no local cluster was configured. | ||
| */ | ||
| virtual const std::string& localClusterName() const PURE; | ||
|
|
||
| virtual void addClusterUpdateCallbacks(ClusterUpdateCallbacks& callbacks) PURE; | ||
| virtual void removeClusterUpdateCallbacks(ClusterUpdateCallbacks& callbacks) PURE; | ||
|
|
||
| virtual LazyLoader* lazyLoader() const PURE; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of these need comments as above. |
||
| }; | ||
|
|
||
| typedef std::unique_ptr<ClusterManager> ClusterManagerPtr; | ||
|
|
@@ -213,7 +228,8 @@ class ClusterManagerFactory { | |
| virtual ClusterSharedPtr clusterFromProto(const envoy::api::v2::Cluster& cluster, | ||
| ClusterManager& cm, | ||
| Outlier::EventLoggerSharedPtr outlier_event_logger, | ||
| bool added_via_api) PURE; | ||
| bool added_via_api, | ||
| bool added_lazily) PURE; | ||
|
|
||
| /** | ||
| * Create a CDS API provider from configuration proto. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| #pragma once | ||
|
|
||
| #include <chrono> | ||
| #include <functional> | ||
| #include <memory> | ||
| #include <string> | ||
| #include <unordered_map> | ||
|
|
||
| #include "envoy/access_log/access_log.h" | ||
| #include "envoy/api/v2/cds.pb.h" | ||
| #include "envoy/config/bootstrap/v2/bootstrap.pb.h" | ||
| #include "envoy/config/grpc_mux.h" | ||
| #include "envoy/grpc/async_client_manager.h" | ||
| #include "envoy/http/async_client.h" | ||
| #include "envoy/http/conn_pool.h" | ||
| #include "envoy/local_info/local_info.h" | ||
| #include "envoy/runtime/runtime.h" | ||
| #include "envoy/upstream/load_balancer.h" | ||
| #include "envoy/upstream/thread_local_cluster.h" | ||
| #include "envoy/upstream/upstream.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Upstream { | ||
|
|
||
| /** | ||
| * Lazy loading is only available when using CDS, bootstrap with static clusters will not support | ||
| * lazy loading. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this true if we have independent lazy CDS config source in the bootstrap as in envoyproxy/data-plane-api#524? |
||
| */ | ||
| class LazyLoader { | ||
| public: | ||
| virtual ~LazyLoader() {} | ||
|
|
||
| virtual void loadCluster(const std::string& cluster) PURE; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doxygenate. |
||
| }; | ||
|
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -377,6 +377,8 @@ class ClusterInfo { | |
| */ | ||
| virtual bool addedViaApi() const PURE; | ||
|
|
||
| virtual bool addedLazily() const PURE; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More so than my comment on envoyproxy/data-plane-api#524, I think this is where we might want to think about how to reconcile incremental and lazy loading. As a strawman, I'd suggest there is no difference between an incremental cluster addition on a regular CDS channel and a lazy loaded cluster. WDYT? @mattklein123 as well.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. Ideally if we could extend the xDS API with incremental updates and incremental subscriptions (or hint) we could handle lazy loading with a single stream and reconcile quite a bit of this logic. Has there been any work / discussion on this? Should I start a data-plane-api proposal?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I started a strawman proposal here: envoyproxy/data-plane-api#527
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to spend heads down time with this next week, but at a high level if we can handle lazy loading w/ incremental lets just do incremental. We will get much bigger bang for the buck here. I will focus mostly on helping work through the issues in envoyproxy/data-plane-api#527. |
||
|
|
||
| /** | ||
| * @return the connect timeout for upstream hosts that belong to this cluster. | ||
| */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,7 @@ | |
| #include "common/config/utility.h" | ||
| #include "common/filesystem/filesystem_impl.h" | ||
| #include "common/protobuf/protobuf.h" | ||
| #include "common/upstream/cds_subscription.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Config { | ||
|
|
@@ -40,6 +41,17 @@ class SubscriptionFactory { | |
| Event::Dispatcher& dispatcher, Upstream::ClusterManager& cm, Runtime::RandomGenerator& random, | ||
| Stats::Scope& scope, std::function<Subscription<ResourceType>*()> rest_legacy_constructor, | ||
| const std::string& rest_method, const std::string& grpc_method) { | ||
| return subscriptionFromConfigSource(config, node, dispatcher, cm, random, | ||
| scope, rest_legacy_constructor, cm.adsMux(), rest_method, grpc_method); | ||
| } | ||
|
|
||
| template <class ResourceType> | ||
| static std::unique_ptr<Subscription<ResourceType>> subscriptionFromConfigSource( | ||
| const envoy::api::v2::core::ConfigSource& config, const envoy::api::v2::core::Node& node, | ||
| Event::Dispatcher& dispatcher, Upstream::ClusterManager& cm, Runtime::RandomGenerator& random, | ||
| Stats::Scope& scope, std::function<Subscription<ResourceType>*()> rest_legacy_constructor, | ||
| Config::GrpcMux& ads_mux, | ||
| const std::string& rest_method, const std::string& grpc_method) { | ||
| std::unique_ptr<Subscription<ResourceType>> result; | ||
| SubscriptionStats stats = Utility::generateStats(scope); | ||
| switch (config.config_source_specifier_case()) { | ||
|
|
@@ -79,14 +91,33 @@ class SubscriptionFactory { | |
| break; | ||
| } | ||
| case envoy::api::v2::core::ConfigSource::kAds: { | ||
| result.reset(new GrpcMuxSubscriptionImpl<ResourceType>(cm.adsMux(), stats)); | ||
| result.reset(new GrpcMuxSubscriptionImpl<ResourceType>(ads_mux, stats)); | ||
| break; | ||
| } | ||
| default: | ||
| throw EnvoyException("Missing config source specifier in envoy::api::v2::core::ConfigSource"); | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| static std::unique_ptr<Subscription<envoy::api::v2::Cluster>> cdsSubscriptionFromConfigSource( | ||
| const envoy::api::v2::core::ConfigSource& cds_config, const Optional<envoy::api::v2::core::ConfigSource>& eds_config, | ||
| const LocalInfo::LocalInfo& local_info, | ||
| Event::Dispatcher& dispatcher, Upstream::ClusterManager& cm, Runtime::RandomGenerator& random, | ||
| Stats::Scope& scope, Config::GrpcMux& ads_mux) { | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: superfluous blank line. |
||
| return subscriptionFromConfigSource<envoy::api::v2::Cluster>( | ||
| cds_config, local_info.node(), dispatcher, cm, random, scope, | ||
| [&cds_config, &eds_config, &cm, &dispatcher, &random, &scope, | ||
| &local_info]() -> Config::Subscription<envoy::api::v2::Cluster>* { | ||
| return new Upstream::CdsSubscription(Config::Utility::generateStats(scope), cds_config, | ||
| eds_config, cm, dispatcher, random, local_info); | ||
| }, | ||
| ads_mux, | ||
| "envoy.api.v2.ClusterDiscoveryService.FetchClusters", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See discussion in envoyproxy/data-plane-api#524, I wonder if lazy deserves a new endpoint or not. |
||
| "envoy.api.v2.ClusterDiscoveryService.StreamClusters"); | ||
|
|
||
| } | ||
| }; | ||
|
|
||
| } // namespace Config | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,8 +51,14 @@ envoy_cc_library( | |
|
|
||
| envoy_cc_library( | ||
| name = "cluster_manager_lib", | ||
| srcs = ["cluster_manager_impl.cc"], | ||
| hdrs = ["cluster_manager_impl.h"], | ||
| srcs = [ | ||
| "cluster_manager_impl.cc", | ||
| "lazy_loader_impl.cc", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer to have |
||
| ], | ||
| hdrs = [ | ||
| "cluster_manager_impl.h", | ||
| "lazy_loader_impl.h" | ||
| ], | ||
| deps = [ | ||
| ":cds_api_lib", | ||
| ":load_balancer_lib", | ||
|
|
@@ -67,6 +73,7 @@ envoy_cc_library( | |
| "//include/envoy/ssl:context_manager_interface", | ||
| "//include/envoy/thread_local:thread_local_interface", | ||
| "//include/envoy/upstream:cluster_manager_interface", | ||
| "//include/envoy/upstream:lazy_loader_interface", | ||
| "//source/common/common:enum_to_int", | ||
| "//source/common/common:utility_lib", | ||
| "//source/common/config:cds_json_lib", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs Doxygen comments (see rest of file for examples to mimic style).