[EventEngine] [reland] Migrate `chttp2_server` to use EE DNSResolver (#37901)

<!--

If you know who should review your pull request, please assign it to that
person, otherwise the pull request would get assigned randomly.

If your pull request is for a specific language, please add the appropriate
lang label.

-->

Closes #37901

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37901 from yijiem:dns-migration-chttp2-server-2 70d29b3b6c
PiperOrigin-RevId: 687466646
pull/37751/head
Yijie Ma 1 month ago committed by Copybara-Service
parent da4fb493de
commit 61be7b0070
  1. 5
      bazel/experiments.bzl
  2. 5
      src/core/BUILD
  3. 88
      src/core/ext/transport/chttp2/server/chttp2_server.cc
  4. 3
      src/core/lib/event_engine/resolved_address.cc
  5. 16
      src/core/lib/event_engine/utils.cc
  6. 7
      src/core/lib/event_engine/utils.h
  7. 27
      src/core/lib/experiments/experiments.cc
  8. 8
      src/core/lib/experiments/experiments.h
  9. 8
      src/core/lib/experiments/experiments.yaml

@ -23,6 +23,7 @@ EXPERIMENT_ENABLES = {
"event_engine_application_callbacks": "event_engine_application_callbacks",
"event_engine_client": "event_engine_client",
"event_engine_dns": "event_engine_dns",
"event_engine_dns_non_client_channel": "event_engine_dns_non_client_channel",
"event_engine_listener": "event_engine_listener",
"free_large_allocator": "free_large_allocator",
"local_connector_secure": "local_connector_secure",
@ -45,6 +46,7 @@ EXPERIMENT_ENABLES = {
EXPERIMENT_POLLERS = [
"event_engine_client",
"event_engine_dns",
"event_engine_dns_non_client_channel",
"event_engine_listener",
]
@ -54,6 +56,7 @@ EXPERIMENTS = {
},
"off": {
"core_end2end_test": [
"event_engine_dns_non_client_channel",
"local_connector_secure",
],
"endpoint_test": [
@ -103,6 +106,7 @@ EXPERIMENTS = {
},
"off": {
"core_end2end_test": [
"event_engine_dns_non_client_channel",
"local_connector_secure",
],
"endpoint_test": [
@ -136,6 +140,7 @@ EXPERIMENTS = {
},
"off": {
"core_end2end_test": [
"event_engine_dns_non_client_channel",
"local_connector_secure",
],
"endpoint_test": [

@ -2378,9 +2378,11 @@ grpc_cc_library(
hdrs = ["lib/event_engine/utils.h"],
external_deps = [
"absl/log:check",
"absl/status:statusor",
"absl/strings",
],
deps = [
"notification",
"time",
"//:event_engine_base_hdrs",
"//:gpr_platform",
@ -7658,8 +7660,11 @@ grpc_cc_library(
"connection_quota",
"error",
"error_utils",
"event_engine_common",
"event_engine_extensions",
"event_engine_query_extensions",
"event_engine_tcp_socket_utils",
"event_engine_utils",
"grpc_insecure_credentials",
"handshaker_registry",
"iomgr_fwd",

@ -59,6 +59,9 @@
#include "src/core/lib/event_engine/channel_args_endpoint_config.h"
#include "src/core/lib/event_engine/extensions/supports_fd.h"
#include "src/core/lib/event_engine/query_extensions.h"
#include "src/core/lib/event_engine/resolved_address_internal.h"
#include "src/core/lib/event_engine/tcp_socket_utils.h"
#include "src/core/lib/event_engine/utils.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/event_engine_shims/endpoint.h"
@ -113,7 +116,8 @@ using AcceptorPtr = std::unique_ptr<grpc_tcp_server_acceptor, AcceptorDeleter>;
class Chttp2ServerListener : public Server::ListenerInterface {
public:
static grpc_error_handle Create(Server* server, grpc_resolved_address* addr,
static grpc_error_handle Create(Server* server,
const EventEngine::ResolvedAddress& addr,
const ChannelArgs& args,
Chttp2ServerArgsModifier args_modifier,
int* port_num);
@ -703,8 +707,9 @@ void Chttp2ServerListener::ActiveConnection::OnDrainGraceTimeExpiry() {
//
grpc_error_handle Chttp2ServerListener::Create(
Server* server, grpc_resolved_address* addr, const ChannelArgs& args,
Chttp2ServerArgsModifier args_modifier, int* port_num) {
Server* server, const EventEngine::ResolvedAddress& addr,
const ChannelArgs& args, Chttp2ServerArgsModifier args_modifier,
int* port_num) {
// Create Chttp2ServerListener.
OrphanablePtr<Chttp2ServerListener> listener =
MakeOrphanable<Chttp2ServerListener>(server, args, args_modifier,
@ -716,18 +721,24 @@ grpc_error_handle Chttp2ServerListener::Create(
&listener->tcp_server_shutdown_complete_, ChannelArgsEndpointConfig(args),
OnAccept, listener.get(), &listener->tcp_server_);
if (!error.ok()) return error;
// TODO(yijiem): remove this conversion when we remove all
// grpc_resolved_address usages.
grpc_resolved_address iomgr_addr =
grpc_event_engine::experimental::CreateGRPCResolvedAddress(addr);
if (listener->config_fetcher_ != nullptr) {
listener->resolved_address_ = *addr;
listener->resolved_address_ = iomgr_addr;
// TODO(yashykt): Consider binding so as to be able to return the port
// number.
} else {
error = grpc_tcp_server_add_port(listener->tcp_server_, addr, port_num);
error =
grpc_tcp_server_add_port(listener->tcp_server_, &iomgr_addr, port_num);
if (!error.ok()) return error;
}
// Create channelz node.
if (args.GetBool(GRPC_ARG_ENABLE_CHANNELZ)
.value_or(GRPC_ENABLE_CHANNELZ_DEFAULT)) {
auto string_address = grpc_sockaddr_to_uri(addr);
auto string_address =
grpc_event_engine::experimental::ResolvedAddressToString(addr);
if (!string_address.ok()) {
return GRPC_ERROR_CREATE(string_address.status().ToString());
}
@ -957,37 +968,68 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr,
args_modifier);
}
*port_num = -1;
absl::StatusOr<std::vector<grpc_resolved_address>> resolved_or;
absl::StatusOr<std::vector<grpc_resolved_address>> resolved;
absl::StatusOr<std::vector<EventEngine::ResolvedAddress>> results =
std::vector<EventEngine::ResolvedAddress>();
std::vector<grpc_error_handle> error_list;
std::string parsed_addr = URI::PercentDecode(addr);
absl::string_view parsed_addr_unprefixed{parsed_addr};
// Using lambda to avoid use of goto.
grpc_error_handle error = [&]() {
grpc_error_handle error;
// TODO(ladynana, yijiem): this code does not handle address URIs correctly:
// it's parsing `unix://foo/bar` as path `/foo/bar` when it should be
// parsing it as authority `foo` and path `/bar`. Also add API documentation
// on the valid URIs that grpc_server_add_http2_port accepts.
if (absl::ConsumePrefix(&parsed_addr_unprefixed, kUnixUriPrefix)) {
resolved_or = grpc_resolve_unix_domain_address(parsed_addr_unprefixed);
resolved = grpc_resolve_unix_domain_address(parsed_addr_unprefixed);
GRPC_RETURN_IF_ERROR(resolved.status());
} else if (absl::ConsumePrefix(&parsed_addr_unprefixed,
kUnixAbstractUriPrefix)) {
resolved_or =
resolved =
grpc_resolve_unix_abstract_domain_address(parsed_addr_unprefixed);
GRPC_RETURN_IF_ERROR(resolved.status());
} else if (absl::ConsumePrefix(&parsed_addr_unprefixed, kVSockUriPrefix)) {
resolved_or = grpc_resolve_vsock_address(parsed_addr_unprefixed);
resolved = grpc_resolve_vsock_address(parsed_addr_unprefixed);
GRPC_RETURN_IF_ERROR(resolved.status());
} else {
if (IsEventEngineDnsNonClientChannelEnabled()) {
absl::StatusOr<std::unique_ptr<EventEngine::DNSResolver>> ee_resolver =
args.GetObjectRef<EventEngine>()->GetDNSResolver(
EventEngine::DNSResolver::ResolverOptions());
GRPC_RETURN_IF_ERROR(ee_resolver.status());
results = grpc_event_engine::experimental::LookupHostnameBlocking(
ee_resolver->get(), parsed_addr, "https");
} else {
resolved_or =
// TODO(yijiem): Remove this after event_engine_dns_non_client_channel
// is fully enabled.
absl::StatusOr<std::vector<grpc_resolved_address>> iomgr_results =
GetDNSResolver()->LookupHostnameBlocking(parsed_addr, "https");
GRPC_RETURN_IF_ERROR(iomgr_results.status());
for (const auto& addr : *iomgr_results) {
results->push_back(
grpc_event_engine::experimental::CreateResolvedAddress(addr));
}
}
if (!resolved_or.ok()) {
return absl_status_to_grpc_error(resolved_or.status());
}
if (resolved.ok()) {
for (const auto& addr : *resolved) {
results->push_back(
grpc_event_engine::experimental::CreateResolvedAddress(addr));
}
}
GRPC_RETURN_IF_ERROR(results.status());
// Create a listener for each resolved address.
for (auto& addr : *resolved_or) {
for (EventEngine::ResolvedAddress& addr : *results) {
// If address has a wildcard port (0), use the same port as a previous
// listener.
if (*port_num != -1 && grpc_sockaddr_get_port(&addr) == 0) {
grpc_sockaddr_set_port(&addr, *port_num);
if (*port_num != -1 &&
grpc_event_engine::experimental::ResolvedAddressGetPort(addr) == 0) {
grpc_event_engine::experimental::ResolvedAddressSetPort(addr,
*port_num);
}
int port_temp = -1;
error = Chttp2ServerListener::Create(server, &addr, args, args_modifier,
error = Chttp2ServerListener::Create(server, addr, args, args_modifier,
&port_temp);
if (!error.ok()) {
error_list.push_back(error);
@ -999,17 +1041,17 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr,
}
}
}
if (error_list.size() == resolved_or->size()) {
if (error_list.size() == results->size()) {
std::string msg = absl::StrFormat(
"No address added out of total %" PRIuPTR " resolved for '%s'",
resolved_or->size(), addr);
results->size(), addr);
return GRPC_ERROR_CREATE_REFERENCING(msg.c_str(), error_list.data(),
error_list.size());
} else if (!error_list.empty()) {
std::string msg = absl::StrFormat(
"Only %" PRIuPTR " addresses added out of total %" PRIuPTR
" resolved",
resolved_or->size() - error_list.size(), resolved_or->size());
std::string msg =
absl::StrFormat("Only %" PRIuPTR
" addresses added out of total %" PRIuPTR " resolved",
results->size() - error_list.size(), results->size());
error = GRPC_ERROR_CREATE_REFERENCING(msg.c_str(), error_list.data(),
error_list.size());
LOG(INFO) << "WARNING: " << StatusToString(error);

@ -48,6 +48,9 @@ EventEngine::ResolvedAddress CreateResolvedAddress(
grpc_resolved_address CreateGRPCResolvedAddress(
const EventEngine::ResolvedAddress& ra) {
static_assert(
GRPC_MAX_SOCKADDR_SIZE == EventEngine::ResolvedAddress::MAX_SIZE_BYTES,
"size should match");
grpc_resolved_address grpc_addr;
memset(&grpc_addr, 0, sizeof(grpc_resolved_address));
memcpy(grpc_addr.addr, ra.address(), ra.size());

@ -20,6 +20,7 @@
#include <algorithm>
#include "absl/strings/str_cat.h"
#include "src/core/util/notification.h"
#include "src/core/util/time.h"
namespace grpc_event_engine {
@ -38,5 +39,20 @@ grpc_core::Timestamp ToTimestamp(grpc_core::Timestamp now,
grpc_core::Duration::Milliseconds(1);
}
absl::StatusOr<std::vector<EventEngine::ResolvedAddress>>
LookupHostnameBlocking(EventEngine::DNSResolver* dns_resolver,
absl::string_view name, absl::string_view default_port) {
absl::StatusOr<std::vector<EventEngine::ResolvedAddress>> results;
grpc_core::Notification done;
dns_resolver->LookupHostname(
[&](absl::StatusOr<std::vector<EventEngine::ResolvedAddress>> addresses) {
results = std::move(addresses);
done.Notify();
},
name, default_port);
done.WaitForNotification();
return results;
}
} // namespace experimental
} // namespace grpc_event_engine

@ -19,7 +19,10 @@
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "src/core/util/time.h"
namespace grpc_event_engine {
@ -36,6 +39,10 @@ std::string HandleToString(const Handle& handle) {
grpc_core::Timestamp ToTimestamp(grpc_core::Timestamp now,
EventEngine::Duration delta);
absl::StatusOr<std::vector<EventEngine::ResolvedAddress>>
LookupHostnameBlocking(EventEngine::DNSResolver* dns_resolver,
absl::string_view name, absl::string_view default_port);
} // namespace experimental
} // namespace grpc_event_engine

@ -41,6 +41,11 @@ const char* const additional_constraints_event_engine_client = "{}";
const char* const description_event_engine_dns =
"If set, use EventEngine DNSResolver for client channel resolution";
const char* const additional_constraints_event_engine_dns = "{}";
const char* const description_event_engine_dns_non_client_channel =
"If set, use EventEngine DNSResolver in other places besides client "
"channel.";
const char* const additional_constraints_event_engine_dns_non_client_channel =
"{}";
const char* const description_event_engine_listener =
"Use EventEngine listeners instead of iomgr's grpc_tcp_server";
const char* const additional_constraints_event_engine_listener = "{}";
@ -122,6 +127,10 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_event_engine_client, nullptr, 0, false, true},
{"event_engine_dns", description_event_engine_dns,
additional_constraints_event_engine_dns, nullptr, 0, false, false},
{"event_engine_dns_non_client_channel",
description_event_engine_dns_non_client_channel,
additional_constraints_event_engine_dns_non_client_channel, nullptr, 0,
false, false},
{"event_engine_listener", description_event_engine_listener,
additional_constraints_event_engine_listener, nullptr, 0, false, true},
{"free_large_allocator", description_free_large_allocator,
@ -188,6 +197,11 @@ const char* const additional_constraints_event_engine_client = "{}";
const char* const description_event_engine_dns =
"If set, use EventEngine DNSResolver for client channel resolution";
const char* const additional_constraints_event_engine_dns = "{}";
const char* const description_event_engine_dns_non_client_channel =
"If set, use EventEngine DNSResolver in other places besides client "
"channel.";
const char* const additional_constraints_event_engine_dns_non_client_channel =
"{}";
const char* const description_event_engine_listener =
"Use EventEngine listeners instead of iomgr's grpc_tcp_server";
const char* const additional_constraints_event_engine_listener = "{}";
@ -269,6 +283,10 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_event_engine_client, nullptr, 0, true, true},
{"event_engine_dns", description_event_engine_dns,
additional_constraints_event_engine_dns, nullptr, 0, true, false},
{"event_engine_dns_non_client_channel",
description_event_engine_dns_non_client_channel,
additional_constraints_event_engine_dns_non_client_channel, nullptr, 0,
false, false},
{"event_engine_listener", description_event_engine_listener,
additional_constraints_event_engine_listener, nullptr, 0, true, true},
{"free_large_allocator", description_free_large_allocator,
@ -335,6 +353,11 @@ const char* const additional_constraints_event_engine_client = "{}";
const char* const description_event_engine_dns =
"If set, use EventEngine DNSResolver for client channel resolution";
const char* const additional_constraints_event_engine_dns = "{}";
const char* const description_event_engine_dns_non_client_channel =
"If set, use EventEngine DNSResolver in other places besides client "
"channel.";
const char* const additional_constraints_event_engine_dns_non_client_channel =
"{}";
const char* const description_event_engine_listener =
"Use EventEngine listeners instead of iomgr's grpc_tcp_server";
const char* const additional_constraints_event_engine_listener = "{}";
@ -416,6 +439,10 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_event_engine_client, nullptr, 0, true, true},
{"event_engine_dns", description_event_engine_dns,
additional_constraints_event_engine_dns, nullptr, 0, true, false},
{"event_engine_dns_non_client_channel",
description_event_engine_dns_non_client_channel,
additional_constraints_event_engine_dns_non_client_channel, nullptr, 0,
false, false},
{"event_engine_listener", description_event_engine_listener,
additional_constraints_event_engine_listener, nullptr, 0, true, true},
{"free_large_allocator", description_free_large_allocator,

@ -65,6 +65,7 @@ inline bool IsClientPrivacyEnabled() { return false; }
inline bool IsEventEngineApplicationCallbacksEnabled() { return true; }
inline bool IsEventEngineClientEnabled() { return false; }
inline bool IsEventEngineDnsEnabled() { return false; }
inline bool IsEventEngineDnsNonClientChannelEnabled() { return false; }
inline bool IsEventEngineListenerEnabled() { return false; }
inline bool IsFreeLargeAllocatorEnabled() { return false; }
inline bool IsLocalConnectorSecureEnabled() { return false; }
@ -98,6 +99,7 @@ inline bool IsEventEngineApplicationCallbacksEnabled() { return true; }
inline bool IsEventEngineClientEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_DNS
inline bool IsEventEngineDnsEnabled() { return true; }
inline bool IsEventEngineDnsNonClientChannelEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
inline bool IsEventEngineListenerEnabled() { return true; }
inline bool IsFreeLargeAllocatorEnabled() { return false; }
@ -132,6 +134,7 @@ inline bool IsEventEngineApplicationCallbacksEnabled() { return true; }
inline bool IsEventEngineClientEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_DNS
inline bool IsEventEngineDnsEnabled() { return true; }
inline bool IsEventEngineDnsNonClientChannelEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
inline bool IsEventEngineListenerEnabled() { return true; }
inline bool IsFreeLargeAllocatorEnabled() { return false; }
@ -165,6 +168,7 @@ enum ExperimentIds {
kExperimentIdEventEngineApplicationCallbacks,
kExperimentIdEventEngineClient,
kExperimentIdEventEngineDns,
kExperimentIdEventEngineDnsNonClientChannel,
kExperimentIdEventEngineListener,
kExperimentIdFreeLargeAllocator,
kExperimentIdLocalConnectorSecure,
@ -208,6 +212,10 @@ inline bool IsEventEngineClientEnabled() {
inline bool IsEventEngineDnsEnabled() {
return IsExperimentEnabled<kExperimentIdEventEngineDns>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_DNS_NON_CLIENT_CHANNEL
inline bool IsEventEngineDnsNonClientChannelEnabled() {
return IsExperimentEnabled<kExperimentIdEventEngineDnsNonClientChannel>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
inline bool IsEventEngineListenerEnabled() {
return IsExperimentEnabled<kExperimentIdEventEngineListener>();

@ -77,6 +77,14 @@
test_tags: ["cancel_ares_query_test", "resolver_component_tests_runner_invoker"]
allow_in_fuzzing_config: false
uses_polling: true
- name: event_engine_dns_non_client_channel
description:
If set, use EventEngine DNSResolver in other places besides client channel.
expiry: 2025/03/01
owner: yijiem@google.com
test_tags: ["core_end2end_test"]
allow_in_fuzzing_config: false
uses_polling: true
- name: event_engine_listener
description: Use EventEngine listeners instead of iomgr's grpc_tcp_server
expiry: 2025/03/01

Loading…
Cancel
Save