-
Notifications
You must be signed in to change notification settings - Fork 5.6k
c-ares: make qcache_max_ttl configurable #45073
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
Changes from all commits
5ca834f
6b01a7a
58b7981
523ea4d
d998991
f1195d6
db1fbed
c927673
957965f
2f31aa0
532cde6
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 |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Share DNSResolver if c-ares config is the same. This is so that qcache can be enabled and shared | ||
| across clusters. This behavior can be reverted by setting the runtime guard | ||
| ``envoy.restart_features.shared_cares_dns_resolver`` to ``false``. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Added qcache_max_ttl to CaresDnsResolverConfig. Default is 0 which means disabled to preserve existing behavior. |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |||
| #include "source/common/protobuf/utility.h" | ||||
| #include "source/common/runtime/runtime_features.h" | ||||
|
|
||||
| #include "absl/container/flat_hash_map.h" | ||||
| #include "absl/strings/str_join.h" | ||||
| #include "ares.h" | ||||
|
|
||||
|
|
@@ -36,7 +37,17 @@ namespace { | |||
| // to their original values: 5 second timeout and 4 retry attempts. | ||||
| // Ref: https://github.com/envoyproxy/envoy/issues/35117 | ||||
| constexpr uint32_t DEFAULT_QUERY_TIMEOUT_SECONDS = 5; | ||||
| constexpr uint32_t DEFAULT_QCACHE_MAX_TTL = 0; | ||||
| constexpr uint32_t DEFAULT_QUERY_TRIES = 4; | ||||
|
|
||||
| uint32_t getQcacheMaxTtl( | ||||
| const envoy::extensions::network::dns_resolver::cares::v3::CaresDnsResolverConfig& config) { | ||||
| if (!config.has_qcache_max_ttl()) { | ||||
| return DEFAULT_QCACHE_MAX_TTL; | ||||
| } | ||||
|
|
||||
| return config.qcache_max_ttl().value(); | ||||
| } | ||||
| } // namespace | ||||
|
|
||||
| DnsResolverImpl::DnsResolverImpl( | ||||
|
|
@@ -63,7 +74,8 @@ DnsResolverImpl::DnsResolverImpl( | |||
| : std::chrono::milliseconds::zero()), | ||||
| reinit_channel_on_timeout_(config.reinit_channel_on_timeout()), resolvers_csv_(resolvers_csv), | ||||
| filter_unroutable_families_(config.filter_unroutable_families()), | ||||
| scope_(root_scope.createScope("dns.cares.")), stats_(generateCaresDnsResolverStats(*scope_)) { | ||||
| scope_(root_scope.createScope("dns.cares.")), stats_(generateCaresDnsResolverStats(*scope_)), | ||||
| max_cache_ttl_(getQcacheMaxTtl(config)) { | ||||
| AresOptions options = defaultAresOptions(); | ||||
| initializeChannel(&options.options_, options.optmask_); | ||||
|
|
||||
|
|
@@ -151,9 +163,11 @@ DnsResolverImpl::AresOptions DnsResolverImpl::defaultAresOptions() { | |||
| options.options_.ednspsz = edns0_max_payload_size_; | ||||
| } | ||||
|
|
||||
| // Disable query cache by default. | ||||
| options.optmask_ |= ARES_OPT_QUERY_CACHE; | ||||
| options.options_.qcache_max_ttl = 0; | ||||
| if (max_cache_ttl_) { | ||||
| ENVOY_LOG(debug, "c-ares query cached enabled: max ttl {}", max_cache_ttl_); | ||||
| } | ||||
| options.options_.qcache_max_ttl = max_cache_ttl_; | ||||
|
|
||||
| return options; | ||||
| } | ||||
|
|
@@ -667,6 +681,19 @@ class CaresDnsResolverFactory : public DnsResolverFactory, | |||
| // Only c-ares DNS factory will call into this function. | ||||
| // Directly unpack the typed config to a c-ares object. | ||||
| RETURN_IF_NOT_OK(Envoy::MessageUtil::unpackTo(typed_dns_resolver_config.typed_config(), cares)); | ||||
| std::size_t key = 0; | ||||
| if (Runtime::runtimeFeatureEnabled("envoy.restart_features.shared_cares_dns_resolver")) { | ||||
| key = MessageUtil::hash(cares); | ||||
| const auto it = resolver_map_.find(key); | ||||
| if (it != resolver_map_.end()) { | ||||
| auto resolver = it->second.lock(); | ||||
| if (resolver) { | ||||
| ENVOY_LOG(trace, "found existing resolvers: {}", key); | ||||
| return resolver; | ||||
| } | ||||
| } | ||||
| } | ||||
|
|
||||
| if (!cares.resolvers().empty()) { | ||||
| const auto& resolver_addrs = cares.resolvers(); | ||||
| resolvers.reserve(resolver_addrs.size()); | ||||
|
|
@@ -678,8 +705,25 @@ class CaresDnsResolverFactory : public DnsResolverFactory, | |||
| } | ||||
| auto csv_or_error = DnsResolverImpl::maybeBuildResolversCsv(resolvers); | ||||
| RETURN_IF_NOT_OK(csv_or_error.status()); | ||||
| return std::make_shared<Network::DnsResolverImpl>(cares, dispatcher, csv_or_error.value(), | ||||
| api.rootScope()); | ||||
|
|
||||
| auto resolver = std::make_shared<Network::DnsResolverImpl>( | ||||
| cares, dispatcher, csv_or_error.value(), api.rootScope()); | ||||
| if (Runtime::runtimeFeatureEnabled("envoy.restart_features.shared_cares_dns_resolver")) { | ||||
| // clean up any nil resolver in the map so it doesn't keep growing | ||||
| auto original_size = resolver_map_.size(); | ||||
| absl::erase_if( | ||||
| resolver_map_, | ||||
| [](const std::pair<const std::size_t, std::weak_ptr<Network::DnsResolver>>& entry) { | ||||
| return entry.second.lock() == nullptr; | ||||
| }); | ||||
| if (resolver_map_.size() < original_size) { | ||||
| ENVOY_LOG(trace, "cleaned up {} entries in resolver_map_", | ||||
| original_size - resolver_map_.size()); | ||||
| } | ||||
| resolver_map_[key] = resolver; | ||||
| ENVOY_LOG(trace, "resolver_map_ size after adding: {}", resolver_map_.size()); | ||||
| } | ||||
| return resolver; | ||||
|
Comment on lines
+709
to
+726
Contributor
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. Guard the insertion and cleanup of auto resolver = std::make_shared<Network::DnsResolverImpl>(
cares, dispatcher, csv_or_error.value(), api.rootScope());
if (Runtime::runtimeFeatureEnabled("envoy.restart_features.shared_cares_dns_resolver")) {
absl::MutexLock lock(&mutex_);
// clean up any nil resolver in the map so it doesn't keep growing
auto original_size = resolver_map_.size();
absl::erase_if(
resolver_map_,
[](const std::pair<const std::size_t, std::weak_ptr<Network::DnsResolver>>& entry) {
return entry.second.lock() == nullptr;
});
if (resolver_map_.size() < original_size) {
ENVOY_LOG(trace, "cleaned up {} entries in resolver_map_",
original_size - resolver_map_.size());
}
resolver_map_[key] = resolver;
ENVOY_LOG(trace, "resolver_map_ size after adding: {}", resolver_map_.size());
}
return resolver;
Contributor
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. switched to use operator[] and ignored the data race comment because it's not true.
Contributor
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. emm, why the data race issue is not true? Considering dns filter might call createDnsResolver() in worker threads concurrently (
Contributor
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. #46577 to revert this PR. PTAL @andy-fong . Please feel free to let me if you think there is no race issue here. |
||||
| } | ||||
|
|
||||
| void initialize() override { | ||||
|
|
@@ -704,6 +748,7 @@ class CaresDnsResolverFactory : public DnsResolverFactory, | |||
| private: | ||||
| bool ares_library_initialized_ ABSL_GUARDED_BY(mutex_){false}; | ||||
| absl::Mutex mutex_; | ||||
| mutable absl::flat_hash_map<std::size_t, std::weak_ptr<Network::DnsResolver>> resolver_map_; | ||||
|
yanavlasov marked this conversation as resolved.
|
||||
| }; | ||||
|
|
||||
| // Register the CaresDnsResolverFactory | ||||
|
|
||||
Uh oh!
There was an error while loading. Please reload this page.