From 8f6ae3599f247c3e0de604b5321538b99f3d68a3 Mon Sep 17 00:00:00 2001 From: AJ Heller Date: Wed, 12 Apr 2023 16:30:01 -0700 Subject: [PATCH] [revert] Revert "Revert "[EventEngine] Implement the EventEngine-driven client channel resolver" (#32768)" (#32772) This is a clean, OSS-only revert of https://github.com/grpc/grpc/pull/32632, but depends on https://github.com/grpc/grpc/pull/32771 landing first, which requires a cherrypick. --- BUILD | 6 +- CMakeLists.txt | 6 + Makefile | 6 + build_autogenerated.yaml | 16 + config.m4 | 5 + config.w32 | 4 + gRPC-C++.podspec | 10 + gRPC-Core.podspec | 13 + grpc.gemspec | 8 + grpc.gyp | 6 + package.xml | 8 + src/core/BUILD | 86 ++- .../resolver/dns/c_ares/dns_resolver_ares.cc | 139 +---- .../resolver/dns/c_ares/dns_resolver_ares.h | 30 + .../resolver/dns/dns_resolver_plugin.cc | 60 ++ .../resolver/dns/dns_resolver_plugin.h | 27 + .../event_engine_client_channel_resolver.cc | 524 ++++++++++++++++++ .../event_engine_client_channel_resolver.h | 35 ++ .../dns/event_engine/service_config_helper.cc | 97 ++++ .../dns/event_engine/service_config_helper.h | 32 ++ .../resolver/dns/native/dns_resolver.cc | 15 +- .../resolver/dns/native/dns_resolver.h | 24 + src/core/lib/event_engine/trace.cc | 1 + src/core/lib/event_engine/trace.h | 6 + src/core/lib/experiments/experiments.cc | 3 + src/core/lib/experiments/experiments.h | 5 +- src/core/lib/experiments/experiments.yaml | 7 + .../plugin_registry/grpc_plugin_registry.cc | 6 +- src/python/grpcio/grpc_core_dependencies.py | 3 + test/cpp/naming/resolver_component_test.cc | 3 +- .../naming/resolver_component_tests_runner.py | 4 +- .../naming/resolver_test_record_groups.yaml | 6 +- tools/doxygen/Doxyfile.c++.internal | 8 + tools/doxygen/Doxyfile.core.internal | 8 + 34 files changed, 1069 insertions(+), 148 deletions(-) create mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h create mode 100644 src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc create mode 100644 src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h create mode 100644 src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc create mode 100644 src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h create mode 100644 src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc create mode 100644 src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h create mode 100644 src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h diff --git a/BUILD b/BUILD index 3405d659afc..0f96f9ca810 100644 --- a/BUILD +++ b/BUILD @@ -783,6 +783,7 @@ grpc_cc_library( "//src/core:grpc_transport_chttp2_server", "//src/core:grpc_transport_inproc", "//src/core:grpc_fault_injection_filter", + "//src/core:grpc_resolver_dns_plugin", ], ) @@ -2954,6 +2955,7 @@ grpc_cc_library( "//src/core:ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc", ], hdrs = [ + "//src/core:ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h", "//src/core:ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h", "//src/core:ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h", ], @@ -2996,12 +2998,10 @@ grpc_cc_library( "//src/core:grpc_sockaddr", "//src/core:iomgr_fwd", "//src/core:iomgr_port", - "//src/core:json", - "//src/core:json_reader", - "//src/core:json_writer", "//src/core:polling_resolver", "//src/core:pollset_set", "//src/core:resolved_address", + "//src/core:service_config_helper", "//src/core:slice", "//src/core:status_helper", "//src/core:time", diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a09675012d..857d8408036 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1622,6 +1622,9 @@ add_library(grpc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc + src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc + src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc + src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc @@ -2637,6 +2640,9 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc + src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc + src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc + src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc src/core/ext/filters/client_channel/resolver/polling_resolver.cc diff --git a/Makefile b/Makefile index 6730a0970a3..8dbd36cea5f 100644 --- a/Makefile +++ b/Makefile @@ -1010,6 +1010,9 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ + src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc \ + src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc \ + src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc \ @@ -1879,6 +1882,9 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ + src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc \ + src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc \ + src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ src/core/ext/filters/client_channel/resolver/polling_resolver.cc \ diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index b5df015c681..64ce260275f 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -243,8 +243,13 @@ libs: - src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h - src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.h - src/core/ext/filters/client_channel/local_subchannel_pool.h + - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h + - src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h + - src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h + - src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h + - src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h - src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h - src/core/ext/filters/client_channel/resolver/polling_resolver.h - src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h @@ -1038,6 +1043,9 @@ libs: - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc + - src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc + - src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc + - src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc - src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc - src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc - src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc @@ -1921,8 +1929,13 @@ libs: - src/core/ext/filters/client_channel/lb_policy/subchannel_list.h - src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/static_stride_scheduler.h - src/core/ext/filters/client_channel/local_subchannel_pool.h + - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h + - src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h + - src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h + - src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h + - src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h - src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h - src/core/ext/filters/client_channel/resolver/polling_resolver.h - src/core/ext/filters/client_channel/retry_filter.h @@ -2326,6 +2339,9 @@ libs: - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc + - src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc + - src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc + - src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc - src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc - src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc - src/core/ext/filters/client_channel/resolver/polling_resolver.cc diff --git a/config.m4 b/config.m4 index 906bdd181bb..d2be9618321 100644 --- a/config.m4 +++ b/config.m4 @@ -90,6 +90,9 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ + src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc \ + src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc \ + src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc \ @@ -1322,7 +1325,9 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/xds) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/binder) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/c_ares) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/event_engine) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/native) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/fake) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/google_c2p) diff --git a/config.w32 b/config.w32 index 20f48cc2aa3..04f6281f689 100644 --- a/config.w32 +++ b/config.w32 @@ -55,6 +55,9 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_posix.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_windows.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\dns_resolver_plugin.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\event_engine\\event_engine_client_channel_resolver.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\event_engine\\service_config_helper.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native\\dns_resolver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\fake\\fake_resolver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\google_c2p\\google_c2p_resolver.cc " + @@ -1322,6 +1325,7 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\binder"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\event_engine"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\fake"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\google_c2p"); diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index b93e89d619c..f5b198c3cb0 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -276,8 +276,13 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.h', 'src/core/ext/filters/client_channel/local_subchannel_pool.h', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h', + 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h', 'src/core/ext/filters/client_channel/resolver/polling_resolver.h', 'src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h', @@ -1311,8 +1316,13 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.h', 'src/core/ext/filters/client_channel/local_subchannel_pool.h', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h', + 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h', 'src/core/ext/filters/client_channel/resolver/polling_resolver.h', 'src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 3874783485e..a25150c6cad 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -288,6 +288,7 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/local_subchannel_pool.h', 'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', @@ -295,7 +296,14 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', + 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h', 'src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc', @@ -2046,8 +2054,13 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.h', 'src/core/ext/filters/client_channel/local_subchannel_pool.h', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h', + 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h', 'src/core/ext/filters/client_channel/resolver/polling_resolver.h', 'src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h', diff --git a/grpc.gemspec b/grpc.gemspec index 4b697fcf561..5a8ee35ae0e 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -194,6 +194,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/local_subchannel_pool.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc ) @@ -201,7 +202,14 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc ) diff --git a/grpc.gyp b/grpc.gyp index e5720ab8205..930ee2393bc 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -314,6 +314,9 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', 'src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc', @@ -1124,6 +1127,9 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', 'src/core/ext/filters/client_channel/resolver/polling_resolver.cc', diff --git a/package.xml b/package.xml index 98884c94092..7568d509f41 100644 --- a/package.xml +++ b/package.xml @@ -176,6 +176,7 @@ + @@ -183,7 +184,14 @@ + + + + + + + diff --git a/src/core/BUILD b/src/core/BUILD index 67d5977b105..3a7531c17cd 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -4893,11 +4893,96 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "service_config_helper", + srcs = ["ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc"], + hdrs = ["ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h"], + external_deps = [ + "absl/status:statusor", + "absl/strings", + ], + language = "c++", + deps = [ + "json", + "json_args", + "json_object_loader", + "json_reader", + "json_writer", + "status_helper", + "//:gpr_platform", + "//:grpc_base", + ], +) + +grpc_cc_library( + name = "grpc_resolver_dns_event_engine", + srcs = ["ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc"], + hdrs = ["ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h"], + external_deps = [ + "absl/base:core_headers", + "absl/cleanup", + "absl/container:flat_hash_set", + "absl/status", + "absl/status:statusor", + "absl/strings", + "absl/types:optional", + ], + language = "c++", + deps = [ + "channel_args", + "event_engine_common", + "event_engine_utils", + "grpc_service_config", + "polling_resolver", + "service_config_helper", + "time", + "validation_errors", + "//:backoff", + "//:debug_location", + "//:gpr", + "//:gpr_platform", + "//:grpc_base", + "//:grpc_grpclb_balancer_addresses", + "//:grpc_resolver", + "//:grpc_service_config_impl", + "//:grpc_trace", + "//:orphanable", + "//:ref_counted_ptr", + "//:server_address", + "//:uri_parser", + ], +) + +grpc_cc_library( + name = "grpc_resolver_dns_plugin", + srcs = [ + "ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc", + ], + hdrs = [ + "ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h", + ], + external_deps = ["absl/strings"], + language = "c++", + deps = [ + "experiments", + "grpc_resolver_dns_event_engine", + "grpc_resolver_dns_native", + "//:config", + "//:config_vars", + "//:gpr", + "//:grpc_resolver", + "//:grpc_resolver_dns_ares", + ], +) + grpc_cc_library( name = "grpc_resolver_dns_native", srcs = [ "ext/filters/client_channel/resolver/dns/native/dns_resolver.cc", ], + hdrs = [ + "ext/filters/client_channel/resolver/dns/native/dns_resolver.h", + ], external_deps = [ "absl/functional:bind_front", "absl/status", @@ -4913,7 +4998,6 @@ grpc_cc_library( "time", "//:backoff", "//:config", - "//:config_vars", "//:debug_location", "//:gpr", "//:grpc_base", diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 4a264dad400..6838ea58a9e 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -17,11 +17,9 @@ #include #include -#include #include #include -#include #include #include #include @@ -40,6 +38,7 @@ #include #include +#include "src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/debug_location.h" @@ -60,8 +59,6 @@ #if GRPC_ARES == 1 -#include - #include #include "absl/container/flat_hash_set.h" @@ -74,11 +71,7 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/config/config_vars.h" #include "src/core/lib/event_engine/handle_containers.h" -#include "src/core/lib/iomgr/gethostname.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/json/json.h" -#include "src/core/lib/json/json_reader.h" -#include "src/core/lib/json/json_writer.h" #include "src/core/lib/resolver/server_address.h" #include "src/core/lib/service_config/service_config_impl.h" #include "src/core/lib/transport/error_utils.h" @@ -237,97 +230,6 @@ OrphanablePtr AresClientChannelDNSResolver::StartRequest() { Ref(DEBUG_LOCATION, "dns-resolving")); } -bool ValueInJsonArray(const Json::Array& array, const char* value) { - for (const Json& entry : array) { - if (entry.type() == Json::Type::kString && entry.string() == value) { - return true; - } - } - return false; -} - -std::string ChooseServiceConfig(char* service_config_choice_json, - grpc_error_handle* error) { - auto json = JsonParse(service_config_choice_json); - if (!json.ok()) { - *error = absl_status_to_grpc_error(json.status()); - return ""; - } - if (json->type() != Json::Type::kArray) { - *error = GRPC_ERROR_CREATE( - "Service Config Choices, error: should be of type array"); - return ""; - } - const Json* service_config = nullptr; - std::vector error_list; - for (const Json& choice : json->array()) { - if (choice.type() != Json::Type::kObject) { - error_list.push_back(GRPC_ERROR_CREATE( - "Service Config Choice, error: should be of type object")); - continue; - } - // Check client language, if specified. - auto it = choice.object().find("clientLanguage"); - if (it != choice.object().end()) { - if (it->second.type() != Json::Type::kArray) { - error_list.push_back(GRPC_ERROR_CREATE( - "field:clientLanguage error:should be of type array")); - } else if (!ValueInJsonArray(it->second.array(), "c++")) { - continue; - } - } - // Check client hostname, if specified. - it = choice.object().find("clientHostname"); - if (it != choice.object().end()) { - if (it->second.type() != Json::Type::kArray) { - error_list.push_back(GRPC_ERROR_CREATE( - "field:clientHostname error:should be of type array")); - } else { - char* hostname = grpc_gethostname(); - if (hostname == nullptr || - !ValueInJsonArray(it->second.array(), hostname)) { - continue; - } - } - } - // Check percentage, if specified. - it = choice.object().find("percentage"); - if (it != choice.object().end()) { - if (it->second.type() != Json::Type::kNumber) { - error_list.push_back(GRPC_ERROR_CREATE( - "field:percentage error:should be of type number")); - } else { - int random_pct = rand() % 100; - int percentage; - if (sscanf(it->second.string().c_str(), "%d", &percentage) != 1) { - error_list.push_back(GRPC_ERROR_CREATE( - "field:percentage error:should be of type integer")); - } else if (random_pct > percentage || percentage == 0) { - continue; - } - } - } - // Found service config. - it = choice.object().find("serviceConfig"); - if (it == choice.object().end()) { - error_list.push_back(GRPC_ERROR_CREATE( - "field:serviceConfig error:required field missing")); - } else if (it->second.type() != Json::Type::kObject) { - error_list.push_back(GRPC_ERROR_CREATE( - "field:serviceConfig error:should be of type object")); - } else if (service_config == nullptr) { - service_config = &it->second; - } - } - if (!error_list.empty()) { - service_config = nullptr; - *error = GRPC_ERROR_CREATE_FROM_VECTOR("Service Config Choices Parser", - &error_list); - } - if (service_config == nullptr) return ""; - return JsonDump(*service_config); -} - void AresClientChannelDNSResolver::AresRequestWrapper::OnHostnameResolved( void* arg, grpc_error_handle error) { auto* self = static_cast(arg); @@ -402,18 +304,16 @@ AresClientChannelDNSResolver::AresRequestWrapper::OnResolvedLocked( result.addresses = ServerAddressList(); } if (service_config_json_ != nullptr) { - grpc_error_handle service_config_error; - std::string service_config_string = - ChooseServiceConfig(service_config_json_, &service_config_error); - if (!service_config_error.ok()) { + auto service_config_string = ChooseServiceConfig(service_config_json_); + if (!service_config_string.ok()) { result.service_config = absl::UnavailableError( absl::StrCat("failed to parse service config: ", - StatusToString(service_config_error))); - } else if (!service_config_string.empty()) { + StatusToString(service_config_string.status()))); + } else if (!service_config_string->empty()) { GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s", - this, service_config_string.c_str()); + this, service_config_string->c_str()); result.service_config = ServiceConfigImpl::Create( - resolver_->channel_args(), service_config_string); + resolver_->channel_args(), *service_config_string); if (!result.service_config.ok()) { result.service_config = absl::UnavailableError( absl::StrCat("failed to parse service config: ", @@ -811,27 +711,22 @@ class AresDNSResolver : public DNSResolver { intptr_t aba_token_ ABSL_GUARDED_BY(mu_) = 0; }; -bool ShouldUseAres(absl::string_view resolver_env) { - return resolver_env.empty() || absl::EqualsIgnoreCase(resolver_env, "ares"); -} +} // namespace -bool UseAresDnsResolver() { - return ShouldUseAres(ConfigVars::Get().DnsResolver()); +bool ShouldUseAresDnsResolver(absl::string_view resolver_env) { + return resolver_env.empty() || absl::EqualsIgnoreCase(resolver_env, "ares"); } -} // namespace - void RegisterAresDnsResolver(CoreConfiguration::Builder* builder) { - if (UseAresDnsResolver()) { - builder->resolver_registry()->RegisterResolverFactory( - std::make_unique()); - } + builder->resolver_registry()->RegisterResolverFactory( + std::make_unique()); } } // namespace grpc_core void grpc_resolver_dns_ares_init() { - if (grpc_core::UseAresDnsResolver()) { + if (grpc_core::ShouldUseAresDnsResolver( + grpc_core::ConfigVars::Get().DnsResolver())) { address_sorting_init(); grpc_error_handle error = grpc_ares_init(); if (!error.ok()) { @@ -843,7 +738,8 @@ void grpc_resolver_dns_ares_init() { } void grpc_resolver_dns_ares_shutdown() { - if (grpc_core::UseAresDnsResolver()) { + if (grpc_core::ShouldUseAresDnsResolver( + grpc_core::ConfigVars::Get().DnsResolver())) { address_sorting_shutdown(); grpc_ares_cleanup(); } @@ -852,6 +748,9 @@ void grpc_resolver_dns_ares_shutdown() { #else // GRPC_ARES == 1 namespace grpc_core { +bool ShouldUseAresDnsResolver(absl::string_view /* resolver_env */) { + return false; +} void RegisterAresDnsResolver(CoreConfiguration::Builder*) {} } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h new file mode 100644 index 00000000000..5b80fe5db40 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h @@ -0,0 +1,30 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_DNS_RESOLVER_ARES_H +#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_DNS_RESOLVER_ARES_H + +#include + +#include "absl/strings/string_view.h" + +#include "src/core/lib/config/core_configuration.h" + +namespace grpc_core { + +bool ShouldUseAresDnsResolver(absl::string_view resolver_env); +void RegisterAresDnsResolver(CoreConfiguration::Builder*); + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_DNS_RESOLVER_ARES_H diff --git a/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc b/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc new file mode 100644 index 00000000000..5aec267e2a0 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc @@ -0,0 +1,60 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include "src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h" + +#include + +#include "absl/strings/match.h" + +#include + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h" +#include "src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h" +#include "src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h" +#include "src/core/lib/config/config_vars.h" +#include "src/core/lib/experiments/experiments.h" +#include "src/core/lib/gprpp/crash.h" +#include "src/core/lib/resolver/resolver_factory.h" + +namespace grpc_core { + +void RegisterDnsResolver(CoreConfiguration::Builder* builder) { + if (IsEventEngineDnsEnabled()) { + gpr_log(GPR_DEBUG, "Using EventEngine dns resolver"); + builder->resolver_registry()->RegisterResolverFactory( + std::make_unique()); + return; + } + auto resolver = ConfigVars::Get().DnsResolver(); + // ---- Ares resolver ---- + if (ShouldUseAresDnsResolver(resolver)) { + gpr_log(GPR_DEBUG, "Using ares dns resolver"); + RegisterAresDnsResolver(builder); + return; + } + // ---- Native resolver ---- + if (absl::EqualsIgnoreCase(resolver, "native") || + !builder->resolver_registry()->HasResolverFactory("dns")) { + gpr_log(GPR_DEBUG, "Using native dns resolver"); + RegisterNativeDnsResolver(builder); + return; + } + Crash( + "Unable to set DNS resolver! Likely a logic error in gRPC-core, " + "please file a bug."); +} + +} // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h b/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h new file mode 100644 index 00000000000..97318f12c6c --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h @@ -0,0 +1,27 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_DNS_RESOLVER_PLUGIN_H +#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_DNS_RESOLVER_PLUGIN_H +#include + +#include "src/core/lib/config/core_configuration.h" + +namespace grpc_core { + +// Centralized decision logic about which client channel DNS resolver to enable. +void RegisterDnsResolver(CoreConfiguration::Builder* builder); + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_DNS_RESOLVER_PLUGIN_H diff --git a/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc new file mode 100644 index 00000000000..78bb58438bb --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc @@ -0,0 +1,524 @@ +// Copyright 2023 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include "src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "absl/base/thread_annotations.h" +#include "absl/cleanup/cleanup.h" +#include "absl/container/flat_hash_set.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/strip.h" +#include "absl/types/optional.h" + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h" +#include "src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h" +#include "src/core/ext/filters/client_channel/resolver/polling_resolver.h" +#include "src/core/lib/backoff/backoff.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/event_engine/handle_containers.h" +#include "src/core/lib/event_engine/resolved_address_internal.h" +#include "src/core/lib/event_engine/utils.h" +#include "src/core/lib/gprpp/debug_location.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/time.h" +#include "src/core/lib/gprpp/validation_errors.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/resolver/resolver.h" +#include "src/core/lib/resolver/resolver_factory.h" +#include "src/core/lib/resolver/server_address.h" +#include "src/core/lib/service_config/service_config.h" +#include "src/core/lib/service_config/service_config_impl.h" + +// IWYU pragma: no_include + +namespace grpc_core { +namespace { + +#define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1 +#define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6 +#define GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS 120 +#define GRPC_DNS_RECONNECT_JITTER 0.2 +#define GRPC_DNS_DEFAULT_QUERY_TIMEOUT_MS 120000 + +using grpc_event_engine::experimental::EventEngine; +using grpc_event_engine::experimental::HandleToString; +using grpc_event_engine::experimental::LookupTaskHandleSet; + +// TODO(hork): Investigate adding a resolver test scenario where the first +// balancer hostname lookup result is an error, and the second contains valid +// addresses. +// TODO(hork): Add a test that checks for proper authority from balancer +// addresses. + +// TODO(hork): replace this with `dns_resolver` when all other resolver +// implementations are removed. +TraceFlag grpc_event_engine_client_channel_resolver_trace( + false, "event_engine_client_channel_resolver"); + +#define GRPC_EVENT_ENGINE_RESOLVER_TRACE(format, ...) \ + if (GRPC_TRACE_FLAG_ENABLED( \ + grpc_event_engine_client_channel_resolver_trace)) { \ + gpr_log(GPR_DEBUG, "(event_engine client channel resolver) " format, \ + __VA_ARGS__); \ + } + +// ---------------------------------------------------------------------------- +// EventEngineClientChannelDNSResolver +// ---------------------------------------------------------------------------- +class EventEngineClientChannelDNSResolver : public PollingResolver { + public: + EventEngineClientChannelDNSResolver(ResolverArgs args, + Duration min_time_between_resolutions); + OrphanablePtr StartRequest() override; + + private: + // ---------------------------------------------------------------------------- + // EventEngineDNSRequestWrapper declaration + // ---------------------------------------------------------------------------- + class EventEngineDNSRequestWrapper + : public InternallyRefCounted { + public: + EventEngineDNSRequestWrapper( + RefCountedPtr resolver, + std::unique_ptr event_engine_resolver); + ~EventEngineDNSRequestWrapper() override; + + // Note that thread safety cannot be analyzed due to this being invoked from + // OrphanablePtr<>, and there's no way to pass the lock annotation through + // there. + void Orphan() override ABSL_NO_THREAD_SAFETY_ANALYSIS; + + private: + void OnHostnameResolved( + absl::StatusOr> addresses); + void OnSRVResolved( + absl::StatusOr> + srv_records); + void OnBalancerHostnamesResolved( + std::string authority, + absl::StatusOr> addresses); + void OnTXTResolved(absl::StatusOr service_config); + // Returns a Result if resolution is complete. + // callers must release the lock and call OnRequestComplete if a Result is + // returned. This is because OnRequestComplete may Orphan the resolver, + // which requires taking the lock. + absl::optional OnResolvedLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(on_resolved_mu_); + // Helper method to populate server addresses on resolver result. + void MaybePopulateAddressesLocked(Resolver::Result* result) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(on_resolved_mu_); + // Helper method to populate balancer addresses on resolver result. + void MaybePopulateBalancerAddressesLocked(Resolver::Result* result) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(on_resolved_mu_); + // Helper method to populate service config on resolver result. + void MaybePopulateServiceConfigLocked(Resolver::Result* result) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(on_resolved_mu_); + + RefCountedPtr resolver_; + Mutex on_resolved_mu_; + // Lookup callbacks + absl::optional hostname_handle_ + ABSL_GUARDED_BY(on_resolved_mu_); + absl::optional srv_handle_ + ABSL_GUARDED_BY(on_resolved_mu_); + absl::optional txt_handle_ + ABSL_GUARDED_BY(on_resolved_mu_); + LookupTaskHandleSet balancer_hostname_handles_ + ABSL_GUARDED_BY(on_resolved_mu_); + // Output fields from requests. + ServerAddressList addresses_ ABSL_GUARDED_BY(on_resolved_mu_); + ServerAddressList balancer_addresses_ ABSL_GUARDED_BY(on_resolved_mu_); + ValidationErrors errors_ ABSL_GUARDED_BY(on_resolved_mu_); + absl::StatusOr service_config_json_ + ABSL_GUARDED_BY(on_resolved_mu_); + // Other internal state + size_t number_of_balancer_hostnames_resolved_ + ABSL_GUARDED_BY(on_resolved_mu_) = 0; + bool orphaned_ ABSL_GUARDED_BY(on_resolved_mu_) = false; + std::unique_ptr event_engine_resolver_; + }; + + /// whether to request the service config + const bool request_service_config_; + // whether or not to enable SRV DNS queries + const bool enable_srv_queries_; + // timeout in milliseconds for active DNS queries + EventEngine::Duration query_timeout_ms_; + std::shared_ptr event_engine_; +}; + +EventEngineClientChannelDNSResolver::EventEngineClientChannelDNSResolver( + ResolverArgs args, Duration min_time_between_resolutions) + : PollingResolver(std::move(args), min_time_between_resolutions, + BackOff::Options() + .set_initial_backoff(Duration::Milliseconds( + GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000)) + .set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER) + .set_jitter(GRPC_DNS_RECONNECT_JITTER) + .set_max_backoff(Duration::Milliseconds( + GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)), + &grpc_event_engine_client_channel_resolver_trace), + request_service_config_( + !channel_args() + .GetBool(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION) + .value_or(true)), + enable_srv_queries_(channel_args() + .GetBool(GRPC_ARG_DNS_ENABLE_SRV_QUERIES) + .value_or(false)), + // TODO(yijiem): decide if the ares channel arg timeout should be reused. + query_timeout_ms_(std::chrono::milliseconds( + std::max(0, channel_args() + .GetInt(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS) + .value_or(GRPC_DNS_DEFAULT_QUERY_TIMEOUT_MS)))), + event_engine_(channel_args().GetObjectRef()) {} + +OrphanablePtr EventEngineClientChannelDNSResolver::StartRequest() { + return MakeOrphanable( + Ref(DEBUG_LOCATION, "dns-resolving"), + event_engine_->GetDNSResolver({/*dns_server=*/authority()})); +} + +// ---------------------------------------------------------------------------- +// EventEngineDNSRequestWrapper definition +// ---------------------------------------------------------------------------- + +EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + EventEngineDNSRequestWrapper( + RefCountedPtr resolver, + std::unique_ptr event_engine_resolver) + : resolver_(std::move(resolver)), + event_engine_resolver_(std::move(event_engine_resolver)) { + // Locking to prevent completion before all records are queried + MutexLock lock(&on_resolved_mu_); + GRPC_EVENT_ENGINE_RESOLVER_TRACE( + "DNSResolver::%p Starting hostname resolution for %s", resolver_.get(), + resolver_->name_to_resolve().c_str()); + hostname_handle_ = event_engine_resolver_->LookupHostname( + [self = Ref(DEBUG_LOCATION, "OnHostnameResolved")]( + absl::StatusOr> addresses) { + self->OnHostnameResolved(std::move(addresses)); + }, + resolver_->name_to_resolve(), kDefaultSecurePort, + resolver_->query_timeout_ms_); + GRPC_EVENT_ENGINE_RESOLVER_TRACE("hostname lookup handle: %s", + HandleToString(*hostname_handle_).c_str()); + if (resolver_->enable_srv_queries_) { + GRPC_EVENT_ENGINE_RESOLVER_TRACE( + "DNSResolver::%p Starting SRV record resolution for %s", + resolver_.get(), resolver_->name_to_resolve().c_str()); + srv_handle_ = event_engine_resolver_->LookupSRV( + [self = Ref(DEBUG_LOCATION, "OnSRVResolved")]( + absl::StatusOr> + srv_records) { self->OnSRVResolved(std::move(srv_records)); }, + resolver_->name_to_resolve(), resolver_->query_timeout_ms_); + GRPC_EVENT_ENGINE_RESOLVER_TRACE("srv lookup handle: %s", + HandleToString(*srv_handle_).c_str()); + } + if (resolver_->request_service_config_) { + GRPC_EVENT_ENGINE_RESOLVER_TRACE( + "DNSResolver::%p Starting TXT record resolution for %s", + resolver_.get(), resolver_->name_to_resolve().c_str()); + txt_handle_ = event_engine_resolver_->LookupTXT( + [self = Ref(DEBUG_LOCATION, "OnTXTResolved")]( + absl::StatusOr service_config) { + self->OnTXTResolved(std::move(service_config)); + }, + absl::StrCat("_grpc_config.", resolver_->name_to_resolve()), + resolver_->query_timeout_ms_); + GRPC_EVENT_ENGINE_RESOLVER_TRACE("txt lookup handle: %s", + HandleToString(*txt_handle_).c_str()); + } +} + +EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + ~EventEngineDNSRequestWrapper() { + resolver_.reset(DEBUG_LOCATION, "dns-resolving"); +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + Orphan() { + { + MutexLock lock(&on_resolved_mu_); + orphaned_ = true; + // Event if cancellation fails here, OnResolvedLocked will return early, and + // the resolver will never see a completed request. + if (hostname_handle_.has_value()) { + event_engine_resolver_->CancelLookup(*hostname_handle_); + } + if (srv_handle_.has_value()) { + event_engine_resolver_->CancelLookup(*srv_handle_); + } + for (const auto& handle : balancer_hostname_handles_) { + event_engine_resolver_->CancelLookup(handle); + } + if (txt_handle_.has_value()) { + event_engine_resolver_->CancelLookup(*txt_handle_); + } + } + Unref(DEBUG_LOCATION, "Orphan"); +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + OnHostnameResolved(absl::StatusOr> + new_addresses) { + ValidationErrors::ScopedField field(&errors_, "hostname lookup"); + absl::optional result; + { + MutexLock lock(&on_resolved_mu_); + if (orphaned_) return; + hostname_handle_.reset(); + if (!new_addresses.ok()) { + errors_.AddError(new_addresses.status().message()); + } else { + addresses_.reserve(addresses_.size() + new_addresses->size()); + for (const auto& addr : *new_addresses) { + addresses_.emplace_back(CreateGRPCResolvedAddress(addr), ChannelArgs()); + } + } + result = OnResolvedLocked(); + } + if (result.has_value()) { + resolver_->OnRequestComplete(std::move(*result)); + } +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + OnSRVResolved( + absl::StatusOr> + srv_records) { + ValidationErrors::ScopedField field(&errors_, "srv lookup"); + absl::optional result; + auto cleanup = absl::MakeCleanup([&]() { + if (result.has_value()) { + resolver_->OnRequestComplete(std::move(*result)); + } + }); + MutexLock lock(&on_resolved_mu_); + if (orphaned_) return; + srv_handle_.reset(); + if (!srv_records.ok()) { + // An error has occurred, finish resolving. + errors_.AddError(srv_records.status().message()); + result = OnResolvedLocked(); + return; + } + // Do a subsequent hostname query since SRV records were returned + for (auto& srv_record : *srv_records) { + GRPC_EVENT_ENGINE_RESOLVER_TRACE( + "DNSResolver::%p Starting balancer hostname resolution for %s:%d", + resolver_.get(), srv_record.host.c_str(), srv_record.port); + auto handle = event_engine_resolver_->LookupHostname( + [host = std::move(srv_record.host), + self = Ref(DEBUG_LOCATION, "OnBalancerHostnamesResolved")]( + absl::StatusOr> + new_balancer_addresses) mutable { + self->OnBalancerHostnamesResolved(std::move(host), + std::move(new_balancer_addresses)); + }, + srv_record.host, std::to_string(srv_record.port), + resolver_->query_timeout_ms_); + GRPC_EVENT_ENGINE_RESOLVER_TRACE("balancer hostname lookup handle: %s", + HandleToString(handle).c_str()); + balancer_hostname_handles_.insert(handle); + } +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + OnBalancerHostnamesResolved( + std::string authority, + absl::StatusOr> + new_balancer_addresses) { + ValidationErrors::ScopedField field( + &errors_, absl::StrCat("balancer lookup for ", authority)); + absl::optional result; + auto cleanup = absl::MakeCleanup([&]() { + if (result.has_value()) { + resolver_->OnRequestComplete(std::move(*result)); + } + }); + MutexLock lock(&on_resolved_mu_); + if (orphaned_) return; + ++number_of_balancer_hostnames_resolved_; + if (!new_balancer_addresses.ok()) { + // An error has occurred, finish resolving. + errors_.AddError(new_balancer_addresses.status().message()); + } else { + // Capture the addresses and finish resolving. + balancer_addresses_.reserve(balancer_addresses_.size() + + new_balancer_addresses->size()); + auto srv_channel_args = + ChannelArgs().Set(GRPC_ARG_DEFAULT_AUTHORITY, authority); + for (const auto& addr : *new_balancer_addresses) { + balancer_addresses_.emplace_back(CreateGRPCResolvedAddress(addr), + srv_channel_args); + } + } + result = OnResolvedLocked(); +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + OnTXTResolved(absl::StatusOr service_config) { + ValidationErrors::ScopedField field(&errors_, "txt lookup"); + absl::optional result; + { + MutexLock lock(&on_resolved_mu_); + if (orphaned_) return; + GPR_ASSERT(txt_handle_.has_value()); + txt_handle_.reset(); + if (!service_config.ok()) { + errors_.AddError(service_config.status().message()); + service_config_json_ = service_config.status(); + } else { + service_config_json_ = absl::StrCat("grpc_config=", *service_config); + } + result = OnResolvedLocked(); + } + if (result.has_value()) { + resolver_->OnRequestComplete(std::move(*result)); + } +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + MaybePopulateAddressesLocked(Resolver::Result* result) { + if (addresses_.empty()) return; + result->addresses = std::move(addresses_); +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + MaybePopulateBalancerAddressesLocked(Resolver::Result* result) { + if (!balancer_addresses_.empty()) { + result->args = + SetGrpcLbBalancerAddresses(result->args, balancer_addresses_); + } +} + +void EventEngineClientChannelDNSResolver::EventEngineDNSRequestWrapper:: + MaybePopulateServiceConfigLocked(Resolver::Result* result) { + // This function is called only if we are returning addresses. In that case, + // we currently ignore TXT lookup failures. + // TODO(roth): Consider differentiating between NXDOMAIN and other failures, + // so that we can return an error in the non-NXDOMAIN case. + if (!service_config_json_.ok()) return; + // TXT lookup succeeded, so parse the config. + auto service_config = ChooseServiceConfig(*service_config_json_); + if (!service_config.ok()) { + result->service_config = absl::UnavailableError(absl::StrCat( + "failed to parse service config: ", service_config.status().message())); + return; + } + if (service_config->empty()) return; + GRPC_EVENT_ENGINE_RESOLVER_TRACE( + "DNSResolver::%p selected service config choice: %s", + event_engine_resolver_.get(), service_config->c_str()); + result->service_config = + ServiceConfigImpl::Create(resolver_->channel_args(), *service_config); + if (!result->service_config.ok()) { + result->service_config = absl::UnavailableError( + absl::StrCat("failed to parse service config: ", + result->service_config.status().message())); + } +} + +absl::optional EventEngineClientChannelDNSResolver:: + EventEngineDNSRequestWrapper::OnResolvedLocked() { + if (orphaned_) return absl::nullopt; + // Wait for all requested queries to return. + if (hostname_handle_.has_value() || srv_handle_.has_value() || + txt_handle_.has_value() || + number_of_balancer_hostnames_resolved_ != + balancer_hostname_handles_.size()) { + GRPC_EVENT_ENGINE_RESOLVER_TRACE( + "DNSResolver::%p OnResolved() waiting for results (hostname: %s, " + "srv: %s, " + "txt: %s, " + "balancer addresses: %" PRIuPTR "/%" PRIuPTR " complete", + this, hostname_handle_.has_value() ? "waiting" : "done", + srv_handle_.has_value() ? "waiting" : "done", + txt_handle_.has_value() ? "waiting" : "done", + number_of_balancer_hostnames_resolved_, + balancer_hostname_handles_.size()); + return absl::nullopt; + } + GRPC_EVENT_ENGINE_RESOLVER_TRACE( + "DNSResolver::%p OnResolvedLocked() proceeding", this); + Resolver::Result result; + result.args = resolver_->channel_args(); + // If both addresses and balancer addresses failed, return an error for both + // addresses and service config. + if (addresses_.empty() && balancer_addresses_.empty()) { + absl::Status status = errors_.status( + absl::StatusCode::kUnavailable, + absl::StrCat("errors resolving ", resolver_->name_to_resolve())); + GRPC_EVENT_ENGINE_RESOLVER_TRACE("%s", status.message().data()); + result.addresses = status; + result.service_config = status; + return std::move(result); + } + if (!errors_.ok()) { + result.resolution_note = errors_.message( + absl::StrCat("errors resolving ", resolver_->name_to_resolve())); + } + // We have at least one of addresses or balancer addresses, so we're going to + // return a non-error for addresses. + result.addresses.emplace(); + MaybePopulateAddressesLocked(&result); + MaybePopulateServiceConfigLocked(&result); + MaybePopulateBalancerAddressesLocked(&result); + return std::move(result); +} + +} // namespace + +bool EventEngineClientChannelDNSResolverFactory::IsValidUri( + const URI& uri) const { + if (absl::StripPrefix(uri.path(), "/").empty()) { + gpr_log(GPR_ERROR, "no server name supplied in dns URI"); + return false; + } + return true; +} + +OrphanablePtr +EventEngineClientChannelDNSResolverFactory::CreateResolver( + ResolverArgs args) const { + Duration min_time_between_resolutions = std::max( + Duration::Zero(), args.args + .GetDurationFromIntMillis( + GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS) + .value_or(Duration::Seconds(30))); + return MakeOrphanable( + std::move(args), min_time_between_resolutions); +} + +} // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h b/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h new file mode 100644 index 00000000000..665b4781787 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h @@ -0,0 +1,35 @@ +// Copyright 2023 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_EVENT_ENGINE_EVENT_ENGINE_CLIENT_CHANNEL_RESOLVER_H +#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_EVENT_ENGINE_EVENT_ENGINE_CLIENT_CHANNEL_RESOLVER_H +#include + +#include "absl/strings/string_view.h" + +#include "src/core/lib/gprpp/orphanable.h" +#include "src/core/lib/resolver/resolver.h" +#include "src/core/lib/resolver/resolver_factory.h" +#include "src/core/lib/uri/uri_parser.h" + +namespace grpc_core { +class EventEngineClientChannelDNSResolverFactory : public ResolverFactory { + public: + absl::string_view scheme() const override { return "dns"; } + bool IsValidUri(const URI& uri) const override; + OrphanablePtr CreateResolver(ResolverArgs args) const override; +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_EVENT_ENGINE_EVENT_ENGINE_CLIENT_CHANNEL_RESOLVER_H diff --git a/src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc b/src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc new file mode 100644 index 00000000000..1f6e2a33f95 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc @@ -0,0 +1,97 @@ +// Copyright 2023 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include "src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h" + +#include + +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + +#include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/iomgr/gethostname.h" +#include "src/core/lib/json/json.h" +#include "src/core/lib/json/json_args.h" +#include "src/core/lib/json/json_object_loader.h" +#include "src/core/lib/json/json_reader.h" +#include "src/core/lib/json/json_writer.h" + +namespace grpc_core { + +namespace { + +struct ServiceConfigChoice { + std::vector client_language; + int percentage = -1; + std::vector client_hostname; + Json::Object service_config; + + static const JsonLoaderInterface* JsonLoader(const JsonArgs&) { + static const auto* loader = + JsonObjectLoader() + .OptionalField("clientLanguage", + &ServiceConfigChoice::client_language) + .OptionalField("percentage", &ServiceConfigChoice::percentage) + .OptionalField("clientHostname", + &ServiceConfigChoice::client_hostname) + .Field("serviceConfig", &ServiceConfigChoice::service_config) + .Finish(); + return loader; + } +}; + +bool vector_contains(const std::vector& v, + const std::string& value) { + return std::find(v.begin(), v.end(), value) != v.end(); +} + +} // namespace + +absl::StatusOr ChooseServiceConfig( + absl::string_view service_config_json) { + auto json = JsonParse(service_config_json); + GRPC_RETURN_IF_ERROR(json.status()); + auto choices = LoadFromJson>(*json); + GRPC_RETURN_IF_ERROR(choices.status()); + for (const ServiceConfigChoice& choice : *choices) { + // Check client language, if specified. + if (!choice.client_language.empty() && + !vector_contains(choice.client_language, "c++")) { + continue; + } + // Check client hostname, if specified. + if (!choice.client_hostname.empty()) { + const char* hostname = grpc_gethostname(); + if (!vector_contains(choice.client_hostname, hostname)) { + continue; + } + } + // Check percentage, if specified. + if (choice.percentage != -1) { + int random_pct = rand() % 100; + if (random_pct > choice.percentage || choice.percentage == 0) { + continue; + } + } + return JsonDump(choice.service_config); + } + // No matching service config was found + return ""; +} + +} // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h b/src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h new file mode 100644 index 00000000000..cbb7f5e9aa6 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h @@ -0,0 +1,32 @@ +// Copyright 2023 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_EVENT_ENGINE_SERVICE_CONFIG_HELPER_H +#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_EVENT_ENGINE_SERVICE_CONFIG_HELPER_H + +#include + +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + +namespace grpc_core { + +absl::StatusOr ChooseServiceConfig( + absl::string_view service_config_json); + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_EVENT_ENGINE_SERVICE_CONFIG_HELPER_H diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc index 7c268fd38c6..019ce8706a8 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc @@ -25,7 +25,6 @@ #include "absl/functional/bind_front.h" #include "absl/status/status.h" #include "absl/status/statusor.h" -#include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" @@ -37,7 +36,6 @@ #include "src/core/ext/filters/client_channel/resolver/polling_resolver.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/debug_location.h" @@ -179,17 +177,8 @@ class NativeClientChannelDNSResolverFactory : public ResolverFactory { } // namespace void RegisterNativeDnsResolver(CoreConfiguration::Builder* builder) { - if (absl::EqualsIgnoreCase(ConfigVars::Get().DnsResolver(), "native")) { - gpr_log(GPR_DEBUG, "Using native dns resolver"); - builder->resolver_registry()->RegisterResolverFactory( - std::make_unique()); - } else { - if (!builder->resolver_registry()->HasResolverFactory("dns")) { - gpr_log(GPR_DEBUG, "Using native dns resolver"); - builder->resolver_registry()->RegisterResolverFactory( - std::make_unique()); - } - } + builder->resolver_registry()->RegisterResolverFactory( + std::make_unique()); } } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h new file mode 100644 index 00000000000..5ab6fb4c8a7 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h @@ -0,0 +1,24 @@ +// Copyright 2022 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_NATIVE_DNS_RESOLVER_H +#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_NATIVE_DNS_RESOLVER_H +#include + +#include "src/core/lib/config/core_configuration.h" + +namespace grpc_core { +void RegisterNativeDnsResolver(CoreConfiguration::Builder* builder); +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_NATIVE_DNS_RESOLVER_H diff --git a/src/core/lib/event_engine/trace.cc b/src/core/lib/event_engine/trace.cc index 991cd2d4775..20ae3ae2341 100644 --- a/src/core/lib/event_engine/trace.cc +++ b/src/core/lib/event_engine/trace.cc @@ -16,6 +16,7 @@ #include "src/core/lib/debug/trace.h" grpc_core::TraceFlag grpc_event_engine_trace(false, "event_engine"); +grpc_core::TraceFlag grpc_event_engine_dns_trace(false, "event_engine_dns"); grpc_core::TraceFlag grpc_event_engine_endpoint_trace(false, "event_engine_endpoint"); grpc_core::TraceFlag grpc_event_engine_endpoint_data_trace( diff --git a/src/core/lib/event_engine/trace.h b/src/core/lib/event_engine/trace.h index 63511d161fc..ddc61706ab3 100644 --- a/src/core/lib/event_engine/trace.h +++ b/src/core/lib/event_engine/trace.h @@ -21,6 +21,7 @@ #include "src/core/lib/debug/trace.h" extern grpc_core::TraceFlag grpc_event_engine_trace; +extern grpc_core::TraceFlag grpc_event_engine_dns_trace; extern grpc_core::TraceFlag grpc_event_engine_endpoint_data_trace; extern grpc_core::TraceFlag grpc_event_engine_poller_trace; extern grpc_core::TraceFlag grpc_event_engine_endpoint_trace; @@ -40,4 +41,9 @@ extern grpc_core::TraceFlag grpc_event_engine_endpoint_trace; gpr_log(GPR_DEBUG, "(event_engine poller) " format, __VA_ARGS__); \ } +#define GRPC_EVENT_ENGINE_DNS_TRACE(format, ...) \ + if (GRPC_TRACE_FLAG_ENABLED(grpc_event_engine_dns_trace)) { \ + gpr_log(GPR_DEBUG, "(event_engine dns) " format, __VA_ARGS__); \ + } + #endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_TRACE_H diff --git a/src/core/lib/experiments/experiments.cc b/src/core/lib/experiments/experiments.cc index 098521d226b..08dfe1ef8ee 100644 --- a/src/core/lib/experiments/experiments.cc +++ b/src/core/lib/experiments/experiments.cc @@ -58,6 +58,8 @@ const char* const description_schedule_cancellation_over_write = "Allow cancellation op to be scheduled over a write"; const char* const description_trace_record_callops = "Enables tracing of call batch initiation and completion."; +const char* const description_event_engine_dns = + "If set, use EventEngine DNSResolver for client channel resolution"; } // namespace namespace grpc_core { @@ -82,6 +84,7 @@ const ExperimentMetadata g_experiment_metadata[] = { {"schedule_cancellation_over_write", description_schedule_cancellation_over_write, false}, {"trace_record_callops", description_trace_record_callops, false}, + {"event_engine_dns", description_event_engine_dns, false}, }; } // namespace grpc_core diff --git a/src/core/lib/experiments/experiments.h b/src/core/lib/experiments/experiments.h index 828a5225f83..2dfa23a025d 100644 --- a/src/core/lib/experiments/experiments.h +++ b/src/core/lib/experiments/experiments.h @@ -74,6 +74,7 @@ inline bool IsTransportSuppliesClientLatencyEnabled() { return false; } inline bool IsEventEngineListenerEnabled() { return false; } inline bool IsScheduleCancellationOverWriteEnabled() { return false; } inline bool IsTraceRecordCallopsEnabled() { return false; } +inline bool IsEventEngineDnsEnabled() { return false; } #else #define GRPC_EXPERIMENT_IS_INCLUDED_TCP_FRAME_SIZE_TUNING inline bool IsTcpFrameSizeTuningEnabled() { return IsExperimentEnabled(0); } @@ -115,8 +116,10 @@ inline bool IsScheduleCancellationOverWriteEnabled() { } #define GRPC_EXPERIMENT_IS_INCLUDED_TRACE_RECORD_CALLOPS inline bool IsTraceRecordCallopsEnabled() { return IsExperimentEnabled(14); } +#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_DNS +inline bool IsEventEngineDnsEnabled() { return IsExperimentEnabled(15); } -constexpr const size_t kNumExperiments = 15; +constexpr const size_t kNumExperiments = 16; extern const ExperimentMetadata g_experiment_metadata[kNumExperiments]; #endif diff --git a/src/core/lib/experiments/experiments.yaml b/src/core/lib/experiments/experiments.yaml index 7435cf58cb6..68bb93130f6 100644 --- a/src/core/lib/experiments/experiments.yaml +++ b/src/core/lib/experiments/experiments.yaml @@ -150,3 +150,10 @@ expiry: 2023/07/01 owner: vigneshbabu@google.com test_tags: [] +- name: event_engine_dns + description: + If set, use EventEngine DNSResolver for client channel resolution + default: false + expiry: 2023/06/01 + owner: yijiem@google.com + test_tags: [] diff --git a/src/core/plugin_registry/grpc_plugin_registry.cc b/src/core/plugin_registry/grpc_plugin_registry.cc index cf0d0b3c0c6..79dd42722e2 100644 --- a/src/core/plugin_registry/grpc_plugin_registry.cc +++ b/src/core/plugin_registry/grpc_plugin_registry.cc @@ -50,9 +50,8 @@ extern void RegisterServiceConfigChannelArgFilter( extern void RegisterExtraFilters(CoreConfiguration::Builder* builder); extern void RegisterResourceQuota(CoreConfiguration::Builder* builder); extern void FaultInjectionFilterRegister(CoreConfiguration::Builder* builder); +extern void RegisterDnsResolver(CoreConfiguration::Builder* builder); extern void RegisterBackendMetricFilter(CoreConfiguration::Builder* builder); -extern void RegisterNativeDnsResolver(CoreConfiguration::Builder* builder); -extern void RegisterAresDnsResolver(CoreConfiguration::Builder* builder); extern void RegisterSockaddrResolver(CoreConfiguration::Builder* builder); extern void RegisterFakeResolver(CoreConfiguration::Builder* builder); extern void RegisterPriorityLbPolicy(CoreConfiguration::Builder* builder); @@ -98,8 +97,7 @@ void BuildCoreConfiguration(CoreConfiguration::Builder* builder) { RegisterServiceConfigChannelArgFilter(builder); RegisterResourceQuota(builder); FaultInjectionFilterRegister(builder); - RegisterAresDnsResolver(builder); - RegisterNativeDnsResolver(builder); + RegisterDnsResolver(builder); RegisterSockaddrResolver(builder); RegisterFakeResolver(builder); RegisterHttpProxyMapper(builder); diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 9975bb561c2..69e97e16ce8 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -64,6 +64,9 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', + 'src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc', + 'src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', 'src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc', diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc index 2d9dd2e2e56..1316143246d 100644 --- a/test/cpp/naming/resolver_component_test.cc +++ b/test/cpp/naming/resolver_component_test.cc @@ -272,7 +272,8 @@ void CheckServiceConfigResultLocked(const char* service_config_json, EXPECT_EQ(service_config_json, args->expected_service_config_string); } if (args->expected_service_config_error.empty()) { - EXPECT_TRUE(service_config_error.ok()); + EXPECT_TRUE(service_config_error.ok()) + << "Actual error: " << service_config_error.ToString(); } else { EXPECT_THAT(service_config_error.ToString(), testing::HasSubstr(args->expected_service_config_error)); diff --git a/test/cpp/naming/resolver_component_tests_runner.py b/test/cpp/naming/resolver_component_tests_runner.py index e9f6768155a..33118701d1a 100755 --- a/test/cpp/naming/resolver_component_tests_runner.py +++ b/test/cpp/naming/resolver_component_tests_runner.py @@ -541,7 +541,7 @@ current_test_subprocess = subprocess.Popen([ '--do_ordered_address_comparison', 'False', '--expected_addrs', '1.2.3.4:443,False', '--expected_chosen_service_config', '', - '--expected_service_config_error', 'field:clientLanguage error:should be of type array', + '--expected_service_config_error', 'clientLanguage error:is not an array', '--expected_lb_policy', '', '--enable_srv_queries', 'True', '--enable_txt_queries', 'True', @@ -559,7 +559,7 @@ current_test_subprocess = subprocess.Popen([ '--do_ordered_address_comparison', 'False', '--expected_addrs', '1.2.3.4:443,False', '--expected_chosen_service_config', '', - '--expected_service_config_error', 'field:percentage error:should be of type number', + '--expected_service_config_error', 'percentage error:failed to parse number', '--expected_lb_policy', '', '--enable_srv_queries', 'True', '--enable_txt_queries', 'True', diff --git a/test/cpp/naming/resolver_test_record_groups.yaml b/test/cpp/naming/resolver_test_record_groups.yaml index 7ff3418e4a7..d459e529c2b 100644 --- a/test/cpp/naming/resolver_test_record_groups.yaml +++ b/test/cpp/naming/resolver_test_record_groups.yaml @@ -403,7 +403,7 @@ resolver_component_tests: - {address: '1.2.3.4:443', is_balancer: false} do_ordered_address_comparison: false expected_chosen_service_config: null - expected_service_config_error: 'field:clientLanguage error:should be of type array' + expected_service_config_error: 'clientLanguage error:is not an array' expected_lb_policy: null enable_srv_queries: true enable_txt_queries: true @@ -419,7 +419,7 @@ resolver_component_tests: - {address: '1.2.3.4:443', is_balancer: false} do_ordered_address_comparison: false expected_chosen_service_config: null - expected_service_config_error: 'field:percentage error:should be of type number' + expected_service_config_error: 'percentage error:failed to parse number' expected_lb_policy: null enable_srv_queries: true enable_txt_queries: true @@ -429,7 +429,7 @@ resolver_component_tests: ipv4-svc_cfg_bad_percentage: - {TTL: '2100', data: 1.2.3.4, type: A} _grpc_config.ipv4-svc_cfg_bad_percentage: - - {TTL: '2100', data: 'grpc_config=[{"percentage":"0","serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"GoService"}],"waitForReady":true}]}},{"clientLanguage":["c++"],"serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService"}],"waitForReady":true}]}}]', + - {TTL: '2100', data: 'grpc_config=[{"percentage":"arst","serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"GoService"}],"waitForReady":true}]}},{"clientLanguage":["c++"],"serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService"}],"waitForReady":true}]}}]', type: TXT} - expected_addrs: - {address: '1.2.3.4:443', is_balancer: false} diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index ffc7d27ec22..a02873896d1 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1151,6 +1151,7 @@ src/core/ext/filters/client_channel/local_subchannel_pool.cc \ src/core/ext/filters/client_channel/local_subchannel_pool.h \ src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ @@ -1158,7 +1159,14 @@ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ +src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc \ +src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ +src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h \ src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index d1de4b40f24..c1b20e05e16 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -960,6 +960,7 @@ src/core/ext/filters/client_channel/resolver/README.md \ src/core/ext/filters/client_channel/resolver/binder/README.md \ src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ @@ -967,8 +968,15 @@ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ +src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.cc \ +src/core/ext/filters/client_channel/resolver/dns/dns_resolver_plugin.h \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.cc \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/event_engine_client_channel_resolver.h \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.cc \ +src/core/ext/filters/client_channel/resolver/dns/event_engine/service_config_helper.h \ src/core/ext/filters/client_channel/resolver/dns/native/README.md \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ +src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.h \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h \ src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc \