From 5962d49b18a1641f6a5c4f4bace7dabecf418dff Mon Sep 17 00:00:00 2001 From: kpavlov00 <kpavlov00@yandex-team.com> Date: Thu, 23 Jan 2025 23:50:10 +0300 Subject: [PATCH] refactor grpc: ClientData clean up commit_hash:68737ed9ce03b32c0f093cea5ba3e97bd7552cac --- .mapping.json | 10 ++- .../userver/ugrpc/client/client_factory.hpp | 40 +--------- .../ugrpc/client/client_factory_settings.hpp | 6 +- .../userver/ugrpc/client/client_settings.hpp | 58 ++++++++++++++ .../{generic.hpp => generic_client.hpp} | 2 +- .../ugrpc/client/impl/channel_factory.hpp | 49 ++++++++++++ .../userver/ugrpc/client/impl/client_data.hpp | 69 +++++++++-------- .../client/impl/codegen_declarations.hpp | 2 +- .../ugrpc/client/simple_client_component.hpp | 2 +- ...tadata.hpp => static_service_metadata.hpp} | 13 ++++ .../include/userver/ugrpc/impl/statistics.hpp | 2 +- .../ugrpc/server/impl/service_worker.hpp | 2 +- .../ugrpc/server/impl/service_worker_impl.hpp | 10 +-- grpc/src/ugrpc/client/client_factory.cpp | 4 +- .../ugrpc/client/client_factory_settings.cpp | 18 +++++ grpc/src/ugrpc/client/client_settings.cpp | 16 ++++ .../{generic.cpp => generic_client.cpp} | 2 +- grpc/src/ugrpc/client/impl/call_params.cpp | 2 +- grpc/src/ugrpc/client/impl/client_data.cpp | 77 ++++--------------- .../ugrpc/client/simple_client_component.cpp | 4 +- grpc/src/ugrpc/impl/statistics.cpp | 2 +- grpc/tests/generic_client_test.cpp | 2 +- samples/grpc-generic-proxy/main.cpp | 2 +- .../grpc-generic-proxy/src/proxy_service.cpp | 2 +- 24 files changed, 235 insertions(+), 161 deletions(-) create mode 100644 grpc/include/userver/ugrpc/client/client_settings.hpp rename grpc/include/userver/ugrpc/client/{generic.hpp => generic_client.hpp} (98%) create mode 100644 grpc/include/userver/ugrpc/client/impl/channel_factory.hpp rename grpc/include/userver/ugrpc/impl/{static_metadata.hpp => static_service_metadata.hpp} (51%) create mode 100644 grpc/src/ugrpc/client/client_factory_settings.cpp create mode 100644 grpc/src/ugrpc/client/client_settings.cpp rename grpc/src/ugrpc/client/{generic.cpp => generic_client.cpp} (97%) diff --git a/.mapping.json b/.mapping.json index 6b8e21c88f23..676bdd5b5af3 100644 --- a/.mapping.json +++ b/.mapping.json @@ -1913,13 +1913,15 @@ "grpc/include/userver/ugrpc/client/client_factory_component.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/client_factory_component.hpp", "grpc/include/userver/ugrpc/client/client_factory_settings.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/client_factory_settings.hpp", "grpc/include/userver/ugrpc/client/client_qos.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/client_qos.hpp", + "grpc/include/userver/ugrpc/client/client_settings.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/client_settings.hpp", "grpc/include/userver/ugrpc/client/common_component.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/common_component.hpp", "grpc/include/userver/ugrpc/client/exceptions.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/exceptions.hpp", "grpc/include/userver/ugrpc/client/fwd.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/fwd.hpp", - "grpc/include/userver/ugrpc/client/generic.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/generic.hpp", + "grpc/include/userver/ugrpc/client/generic_client.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/generic_client.hpp", "grpc/include/userver/ugrpc/client/impl/async_method_invocation.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/impl/async_method_invocation.hpp", "grpc/include/userver/ugrpc/client/impl/async_methods.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/impl/async_methods.hpp", "grpc/include/userver/ugrpc/client/impl/call_params.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/impl/call_params.hpp", + "grpc/include/userver/ugrpc/client/impl/channel_factory.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/impl/channel_factory.hpp", "grpc/include/userver/ugrpc/client/impl/client_data.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/impl/client_data.hpp", "grpc/include/userver/ugrpc/client/impl/codegen_declarations.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/impl/codegen_declarations.hpp", "grpc/include/userver/ugrpc/client/impl/codegen_definitions.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/impl/codegen_definitions.hpp", @@ -1943,7 +1945,7 @@ "grpc/include/userver/ugrpc/impl/protobuf_collector.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/protobuf_collector.hpp", "grpc/include/userver/ugrpc/impl/queue_runner.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/queue_runner.hpp", "grpc/include/userver/ugrpc/impl/span.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/span.hpp", - "grpc/include/userver/ugrpc/impl/static_metadata.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/static_metadata.hpp", + "grpc/include/userver/ugrpc/impl/static_service_metadata.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/static_service_metadata.hpp", "grpc/include/userver/ugrpc/impl/statistics.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/statistics.hpp", "grpc/include/userver/ugrpc/impl/statistics_scope.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/statistics_scope.hpp", "grpc/include/userver/ugrpc/impl/statistics_storage.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/impl/statistics_storage.hpp", @@ -2001,9 +2003,11 @@ "grpc/src/ugrpc/client/channels.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/channels.cpp", "grpc/src/ugrpc/client/client_factory.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/client_factory.cpp", "grpc/src/ugrpc/client/client_factory_component.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/client_factory_component.cpp", + "grpc/src/ugrpc/client/client_factory_settings.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/client_factory_settings.cpp", + "grpc/src/ugrpc/client/client_settings.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/client_settings.cpp", "grpc/src/ugrpc/client/common_component.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/common_component.cpp", "grpc/src/ugrpc/client/exceptions.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/exceptions.cpp", - "grpc/src/ugrpc/client/generic.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/generic.cpp", + "grpc/src/ugrpc/client/generic_client.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/generic_client.cpp", "grpc/src/ugrpc/client/impl/async_method_invocation.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/impl/async_method_invocation.cpp", "grpc/src/ugrpc/client/impl/async_methods.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/impl/async_methods.cpp", "grpc/src/ugrpc/client/impl/call_params.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/impl/call_params.cpp", diff --git a/grpc/include/userver/ugrpc/client/client_factory.hpp b/grpc/include/userver/ugrpc/client/client_factory.hpp index 7eb6e6684c2b..9a5f77033f05 100644 --- a/grpc/include/userver/ugrpc/client/client_factory.hpp +++ b/grpc/include/userver/ugrpc/client/client_factory.hpp @@ -6,15 +6,12 @@ #include <string> #include <utility> -#include <grpcpp/completion_queue.h> -#include <grpcpp/security/credentials.h> - #include <userver/dynamic_config/source.hpp> #include <userver/engine/task/task_processor_fwd.hpp> #include <userver/testsuite/grpc_control.hpp> #include <userver/ugrpc/client/client_factory_settings.hpp> -#include <userver/ugrpc/client/fwd.hpp> +#include <userver/ugrpc/client/client_settings.hpp> #include <userver/ugrpc/client/middlewares/base.hpp> USERVER_NAMESPACE_BEGIN @@ -26,39 +23,6 @@ class CompletionQueuePoolBase; namespace ugrpc::client { -/// Settings relating to creation of a code-generated client -struct ClientSettings final { - /// **(Required)** - /// The name of the client, for diagnostics, credentials and middlewares. - std::string client_name; - - /// **(Required)** - /// The URI to connect to, e.g. `http://my.domain.com:8080`. - /// Should not include any HTTP path, just schema, domain name and port. Unix - /// sockets are also supported. For details, see: - /// https://grpc.github.io/grpc/cpp/md_doc_naming.html - std::string endpoint; - - /// **(Optional)** - /// The name of the QOS - /// @ref scripts/docs/en/userver/dynamic_config.md "dynamic config" - /// that will be applied automatically to every RPC. - /// - /// Timeout from QOS config is ignored if: - /// - /// * an explicit `qos` parameter is specified at RPC creation, or - /// * deadline is specified in the `client_context` passed at RPC creation. - /// - /// ## Client QOS config definition sample - /// - /// @snippet grpc/tests/tests/unit_test_client_qos.hpp qos config key - const dynamic_config::Key<ClientQos>* client_qos{nullptr}; - - /// **(Optional)** - /// Dedicated high-load methods that have separate channels - DedicatedMethodsConfig dedicated_methods_config{}; -}; - /// @ingroup userver_clients /// /// @brief Creates gRPC clients. @@ -92,7 +56,7 @@ class ClientFactory final { ugrpc::impl::CompletionQueuePoolBase& completion_queues, ugrpc::impl::StatisticsStorage& statistics_storage, testsuite::GrpcControl& testsuite_grpc, - dynamic_config::Source source + dynamic_config::Source config_source ); /// @endcond diff --git a/grpc/include/userver/ugrpc/client/client_factory_settings.hpp b/grpc/include/userver/ugrpc/client/client_factory_settings.hpp index 22f6a1987605..7f05222a301e 100644 --- a/grpc/include/userver/ugrpc/client/client_factory_settings.hpp +++ b/grpc/include/userver/ugrpc/client/client_factory_settings.hpp @@ -16,9 +16,6 @@ USERVER_NAMESPACE_BEGIN namespace ugrpc::client { -// method name -> count of channels -using DedicatedMethodsConfig = std::unordered_map<std::string, std::size_t>; - /// Settings relating to the ClientFactory struct ClientFactorySettings final { /// gRPC channel credentials, none by default @@ -41,6 +38,9 @@ struct ClientFactorySettings final { std::size_t channel_count{1}; }; +std::shared_ptr<grpc::ChannelCredentials> +GetClientCredentials(const ClientFactorySettings& client_factory_settings, const std::string& client_name); + } // namespace ugrpc::client USERVER_NAMESPACE_END diff --git a/grpc/include/userver/ugrpc/client/client_settings.hpp b/grpc/include/userver/ugrpc/client/client_settings.hpp new file mode 100644 index 000000000000..3e4913b0e16b --- /dev/null +++ b/grpc/include/userver/ugrpc/client/client_settings.hpp @@ -0,0 +1,58 @@ +#pragma once + +/// @file userver/ugrpc/client/client_settings.hpp +/// @brief @copybrief ugrpc::client::ClientSettings + +#include <cstddef> +#include <string> +#include <unordered_map> + +#include <userver/dynamic_config/snapshot.hpp> + +#include <userver/ugrpc/client/fwd.hpp> + +USERVER_NAMESPACE_BEGIN + +namespace ugrpc::client { + +// rpc method name -> count of channels +using DedicatedMethodsConfig = std::unordered_map<std::string, std::size_t>; + +/// Settings relating to creation of a code-generated client +struct ClientSettings final { + /// **(Required)** + /// The name of the client, for diagnostics, credentials and middlewares. + std::string client_name; + + /// **(Required)** + /// The URI to connect to, e.g. `http://my.domain.com:8080`. + /// Should not include any HTTP path, just schema, domain name and port. Unix + /// sockets are also supported. For details, see: + /// https://grpc.github.io/grpc/cpp/md_doc_naming.html + std::string endpoint; + + /// **(Optional)** + /// The name of the QOS + /// @ref scripts/docs/en/userver/dynamic_config.md "dynamic config" + /// that will be applied automatically to every RPC. + /// + /// Timeout from QOS config is ignored if: + /// + /// * an explicit `qos` parameter is specified at RPC creation, or + /// * deadline is specified in the `client_context` passed at RPC creation. + /// + /// ## Client QOS config definition sample + /// + /// @snippet grpc/tests/tests/unit_test_client_qos.hpp qos config key + const dynamic_config::Key<ClientQos>* client_qos{nullptr}; + + /// **(Optional)** + /// Dedicated high-load methods that have separate channels + DedicatedMethodsConfig dedicated_methods_config{}; +}; + +std::size_t GetMethodChannelCount(const DedicatedMethodsConfig& dedicated_methods_config, std::string_view method_name); + +} // namespace ugrpc::client + +USERVER_NAMESPACE_END diff --git a/grpc/include/userver/ugrpc/client/generic.hpp b/grpc/include/userver/ugrpc/client/generic_client.hpp similarity index 98% rename from grpc/include/userver/ugrpc/client/generic.hpp rename to grpc/include/userver/ugrpc/client/generic_client.hpp index d1d60432a832..310e55567374 100644 --- a/grpc/include/userver/ugrpc/client/generic.hpp +++ b/grpc/include/userver/ugrpc/client/generic_client.hpp @@ -1,6 +1,6 @@ #pragma once -/// @file userver/ugrpc/client/generic.hpp +/// @file userver/ugrpc/client/generic_client.hpp /// @brief @copybrief ugrpc::client::GenericClient #include <optional> diff --git a/grpc/include/userver/ugrpc/client/impl/channel_factory.hpp b/grpc/include/userver/ugrpc/client/impl/channel_factory.hpp new file mode 100644 index 000000000000..4fe951e30aaa --- /dev/null +++ b/grpc/include/userver/ugrpc/client/impl/channel_factory.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include <grpcpp/channel.h> +#include <grpcpp/create_channel.h> +#include <grpcpp/security/credentials.h> +#include <grpcpp/support/channel_arguments.h> + +#include <userver/engine/async.hpp> + +#include <userver/ugrpc/impl/to_string.hpp> + +USERVER_NAMESPACE_BEGIN + +namespace ugrpc::client::impl { + +class ChannelFactory final { +public: + ChannelFactory( + engine::TaskProcessor& blocking_task_processor, + const std::string& endpoint, + std::shared_ptr<grpc::ChannelCredentials> credentials, + const grpc::ChannelArguments& channel_args + ) + : blocking_task_processor_(blocking_task_processor), + endpoint_{ugrpc::impl::ToGrpcString(endpoint)}, + credentials_{std::move(credentials)}, + channel_args_{channel_args} {} + + std::shared_ptr<grpc::Channel> CreateChannel() const { + return engine::AsyncNoSpan( + blocking_task_processor_, + grpc::CreateCustomChannel, + std::ref(endpoint_), + std::ref(credentials_), + std::ref(channel_args_) + ) + .Get(); + } + +private: + engine::TaskProcessor& blocking_task_processor_; + grpc::string endpoint_; + std::shared_ptr<grpc::ChannelCredentials> credentials_; + const grpc::ChannelArguments& channel_args_; +}; + +} // namespace ugrpc::client::impl + +USERVER_NAMESPACE_END diff --git a/grpc/include/userver/ugrpc/client/impl/client_data.hpp b/grpc/include/userver/ugrpc/client/impl/client_data.hpp index 701a5503282c..e5630055ca62 100644 --- a/grpc/include/userver/ugrpc/client/impl/client_data.hpp +++ b/grpc/include/userver/ugrpc/client/impl/client_data.hpp @@ -5,9 +5,7 @@ #include <optional> #include <utility> -#include <grpcpp/channel.h> #include <grpcpp/completion_queue.h> -#include <grpcpp/security/credentials.h> #include <userver/dynamic_config/source.hpp> #include <userver/engine/task/task_processor_fwd.hpp> @@ -15,11 +13,12 @@ #include <userver/utils/fixed_array.hpp> #include <userver/ugrpc/client/client_factory_settings.hpp> +#include <userver/ugrpc/client/client_settings.hpp> #include <userver/ugrpc/client/fwd.hpp> +#include <userver/ugrpc/client/impl/channel_factory.hpp> #include <userver/ugrpc/client/middlewares/fwd.hpp> -#include <userver/ugrpc/impl/static_metadata.hpp> +#include <userver/ugrpc/impl/static_service_metadata.hpp> #include <userver/ugrpc/impl/statistics.hpp> -#include <userver/ugrpc/impl/to_string.hpp> USERVER_NAMESPACE_BEGIN @@ -28,10 +27,6 @@ class StatisticsStorage; class CompletionQueuePoolBase; } // namespace ugrpc::impl -namespace ugrpc::client { -struct ClientFactorySettings; -} - namespace ugrpc::client::impl { /// Contains all non-code-generated dependencies for creating a gRPC client @@ -44,7 +39,7 @@ struct ClientDependencies final { const dynamic_config::Source config_source; testsuite::GrpcControl& testsuite_grpc; const dynamic_config::Key<ClientQos>* qos{nullptr}; - const ClientFactorySettings& settings; + const ClientFactorySettings& client_factory_settings; engine::TaskProcessor& channel_task_processor; DedicatedMethodsConfig dedicated_methods_config; }; @@ -66,14 +61,18 @@ class ClientData final { : dependencies_(std::move(dependencies)), metadata_(metadata), service_statistics_(&GetServiceStatistics()), - channels_(CreateChannels(dependencies_)), + channel_factory_(CreateChannelFactory(dependencies_)), + channels_(CreateChannels(channel_factory_, dependencies_.client_factory_settings.channel_count)), stubs_(MakeStubs<Service>(channels_)), - dedicated_stubs_(MakeDedicatedStubs<Service>(dependencies_, metadata)) {} + dedicated_stubs_( + MakeDedicatedStubs<Service>(channel_factory_, *metadata_, dependencies_.dedicated_methods_config) + ) {} template <typename Service> ClientData(ClientDependencies&& dependencies, GenericClientTag, std::in_place_type_t<Service>) : dependencies_(std::move(dependencies)), - channels_(CreateChannels(dependencies_)), + channel_factory_(CreateChannelFactory(dependencies_)), + channels_(CreateChannels(channel_factory_, dependencies_.client_factory_settings.channel_count)), stubs_(MakeStubs<Service>(channels_)) {} ClientData(ClientData&&) noexcept = default; @@ -118,16 +117,10 @@ class ClientData final { std::size_t GetDedicatedChannelCount(std::size_t method_id) const; private: - static std::shared_ptr<grpc::Channel> - CreateChannelImpl(const ClientDependencies& dependencies, const grpc::string& endpoint); + static ChannelFactory CreateChannelFactory(const ClientDependencies& dependencies); - static utils::FixedArray<std::shared_ptr<grpc::Channel>> CreateChannels(const ClientDependencies& dependencies); - - static std::size_t GetDedicatedChannelCountImpl( - const ClientDependencies& dependencies, - std::size_t method_id, - const ugrpc::impl::StaticServiceMetadata& meta - ); + static utils::FixedArray<std::shared_ptr<grpc::Channel>> + CreateChannels(const ChannelFactory& channel_factory, std::size_t channel_count); using StubDeleterType = void (*)(void*); using StubPtr = std::unique_ptr<void, StubDeleterType>; @@ -140,26 +133,34 @@ class ClientData final { } template <typename Service> - static utils::FixedArray<StubPtr> MakeStubs(const utils::FixedArray<std::shared_ptr<grpc::Channel>>& channels) { + static StubPtr MakeStub(const std::shared_ptr<grpc::Channel>& channel) { + return StubPtr(Service::NewStub(channel).release(), &StubDeleter<Service>); + } + + template <typename Service> + static StubPool MakeStubs(const utils::FixedArray<std::shared_ptr<grpc::Channel>>& channels) { return utils::GenerateFixedArray(channels.size(), [&](std::size_t index) { - return StubPtr(Service::NewStub(channels[index]).release(), &StubDeleter<Service>); + return MakeStub<Service>(channels[index]); }); } template <typename Service> - static utils::FixedArray<StubPool> - MakeDedicatedStubs(const ClientDependencies& dependencies, const ugrpc::impl::StaticServiceMetadata& meta) { - const auto& method_full_names = meta.method_full_names; - const auto endpoint_string = ugrpc::impl::ToGrpcString(dependencies.endpoint); - return utils::GenerateFixedArray(method_full_names.size(), [&](std::size_t method_id) { - const auto dedicated_channel_count = GetDedicatedChannelCountImpl(dependencies, method_id, meta); - return utils::GenerateFixedArray(dedicated_channel_count, [&](std::size_t) { - return StubPtr(Service::NewStub(CreateChannelImpl(dependencies, endpoint_string)).release(), &StubDeleter<Service>); + static utils::FixedArray<StubPool> MakeDedicatedStubs( + const ChannelFactory& channel_factory, + const ugrpc::impl::StaticServiceMetadata& metadata, + const DedicatedMethodsConfig& dedicated_methods_config + ) { + return utils::GenerateFixedArray(GetMethodsCount(metadata), [&](std::size_t method_id) { + const auto method_channel_count = + GetMethodChannelCount(dedicated_methods_config, GetMethodName(metadata, method_id)); + return utils::GenerateFixedArray(method_channel_count, [&](std::size_t) { + const auto channel = channel_factory.CreateChannel(); + return MakeStub<Service>(channel); }); }); } - const StubPtr& NextStubPtr(const utils::FixedArray<StubPtr>& stubs) const; + const StubPtr& NextStubPtr(const StubPool& stubs) const; ugrpc::impl::ServiceStatistics& GetServiceStatistics(); @@ -167,9 +168,11 @@ class ClientData final { std::optional<ugrpc::impl::StaticServiceMetadata> metadata_{std::nullopt}; ugrpc::impl::ServiceStatistics* service_statistics_{nullptr}; + ChannelFactory channel_factory_; + utils::FixedArray<std::shared_ptr<grpc::Channel>> channels_; - utils::FixedArray<StubPtr> stubs_; + StubPool stubs_; // method_id -> stub_pool utils::FixedArray<StubPool> dedicated_stubs_; }; diff --git a/grpc/include/userver/ugrpc/client/impl/codegen_declarations.hpp b/grpc/include/userver/ugrpc/client/impl/codegen_declarations.hpp index 4a97629636a7..4b10faf8f76d 100644 --- a/grpc/include/userver/ugrpc/client/impl/codegen_declarations.hpp +++ b/grpc/include/userver/ugrpc/client/impl/codegen_declarations.hpp @@ -12,5 +12,5 @@ #include <userver/ugrpc/client/qos.hpp> #include <userver/ugrpc/client/response_future.hpp> #include <userver/ugrpc/client/rpc.hpp> -#include <userver/ugrpc/impl/static_metadata.hpp> +#include <userver/ugrpc/impl/static_service_metadata.hpp> #include <userver/ugrpc/impl/statistics.hpp> diff --git a/grpc/include/userver/ugrpc/client/simple_client_component.hpp b/grpc/include/userver/ugrpc/client/simple_client_component.hpp index 118c091f59db..aaca1cf845fa 100644 --- a/grpc/include/userver/ugrpc/client/simple_client_component.hpp +++ b/grpc/include/userver/ugrpc/client/simple_client_component.hpp @@ -64,7 +64,7 @@ class SimpleClientComponentAny : public components::ComponentBase { /// ---- | ----------- | ------------- /// endpoint | URL of the gRPC service | -- /// client-name | name of the gRPC server we talk to, for diagnostics | <uses the component name> -/// dedicated-channel-counts | a map of method names to channel counts. Used for high-load methods | - +/// dedicated-channel-counts | a map of rpc method names to channel counts. Used for high-load methods | - /// factory-component | ClientFactoryComponent name to use for client creation | -- // clang-format on diff --git a/grpc/include/userver/ugrpc/impl/static_metadata.hpp b/grpc/include/userver/ugrpc/impl/static_service_metadata.hpp similarity index 51% rename from grpc/include/userver/ugrpc/impl/static_metadata.hpp rename to grpc/include/userver/ugrpc/impl/static_service_metadata.hpp index 3fb96b7c9906..98e1b1038370 100644 --- a/grpc/include/userver/ugrpc/impl/static_metadata.hpp +++ b/grpc/include/userver/ugrpc/impl/static_service_metadata.hpp @@ -20,6 +20,19 @@ constexpr StaticServiceMetadata MakeStaticServiceMetadata(utils::span<const std: return {GrpcppService::service_full_name(), method_full_names}; } +constexpr std::size_t GetMethodsCount(const StaticServiceMetadata& metadata) noexcept { + return metadata.method_full_names.size(); +} + +constexpr std::string_view GetMethodFullName(const StaticServiceMetadata& metadata, std::size_t method_id) { + return metadata.method_full_names[method_id]; +} + +constexpr std::string_view GetMethodName(const StaticServiceMetadata& metadata, std::size_t method_id) { + const auto& method_full_name = metadata.method_full_names[method_id]; + return method_full_name.substr(metadata.service_full_name.size() + 1); +} + } // namespace ugrpc::impl USERVER_NAMESPACE_END diff --git a/grpc/include/userver/ugrpc/impl/statistics.hpp b/grpc/include/userver/ugrpc/impl/statistics.hpp index 987b675e4f8d..6bc5b1826bf2 100644 --- a/grpc/include/userver/ugrpc/impl/statistics.hpp +++ b/grpc/include/userver/ugrpc/impl/statistics.hpp @@ -7,7 +7,7 @@ #include <string_view> #include <userver/ugrpc/impl/code_statistics.hpp> -#include <userver/ugrpc/impl/static_metadata.hpp> +#include <userver/ugrpc/impl/static_service_metadata.hpp> #include <userver/utils/fixed_array.hpp> #include <userver/utils/statistics/fwd.hpp> diff --git a/grpc/include/userver/ugrpc/server/impl/service_worker.hpp b/grpc/include/userver/ugrpc/server/impl/service_worker.hpp index b2087f7993e6..62b0e75534b3 100644 --- a/grpc/include/userver/ugrpc/server/impl/service_worker.hpp +++ b/grpc/include/userver/ugrpc/server/impl/service_worker.hpp @@ -14,7 +14,7 @@ #include <userver/utils/fixed_array.hpp> #include <userver/utils/statistics/fwd.hpp> -#include <userver/ugrpc/impl/static_metadata.hpp> +#include <userver/ugrpc/impl/static_service_metadata.hpp> #include <userver/ugrpc/impl/statistics_storage.hpp> #include <userver/ugrpc/server/impl/completion_queue_pool.hpp> #include <userver/ugrpc/server/middlewares/fwd.hpp> diff --git a/grpc/include/userver/ugrpc/server/impl/service_worker_impl.hpp b/grpc/include/userver/ugrpc/server/impl/service_worker_impl.hpp index c1bc94f776b0..ce42017aac52 100644 --- a/grpc/include/userver/ugrpc/server/impl/service_worker_impl.hpp +++ b/grpc/include/userver/ugrpc/server/impl/service_worker_impl.hpp @@ -22,7 +22,7 @@ #include <userver/utils/lazy_prvalue.hpp> #include <userver/utils/statistics/entry.hpp> -#include <userver/ugrpc/impl/static_metadata.hpp> +#include <userver/ugrpc/impl/static_service_metadata.hpp> #include <userver/ugrpc/impl/statistics.hpp> #include <userver/ugrpc/impl/statistics_scope.hpp> #include <userver/ugrpc/server/call_context.hpp> @@ -84,7 +84,7 @@ struct ServiceData final { const ServiceSettings settings; const ugrpc::impl::StaticServiceMetadata metadata; - AsyncService<GrpcppService> async_service{metadata.method_full_names.size()}; + AsyncService<GrpcppService> async_service{GetMethodsCount(metadata)}; utils::impl::WaitTokenStorage wait_tokens; ugrpc::impl::ServiceStatistics& service_statistics{ settings.statistics_storage.GetServiceStatistics(metadata, std::nullopt)}; @@ -99,9 +99,9 @@ struct MethodData final { typename CallTraits::ServiceBase& service; const typename CallTraits::ServiceMethod service_method; - std::string_view call_name{service_data.metadata.method_full_names[method_id]}; + std::string_view call_name{GetMethodFullName(service_data.metadata, method_id)}; // Remove name of the service and slash - std::string_view method_name{call_name.substr(service_data.metadata.service_full_name.size() + 1)}; + std::string_view method_name{GetMethodName(service_data.metadata, method_id)}; ugrpc::impl::MethodStatistics& statistics{service_data.service_statistics.GetMethodStatistics(method_id)}; }; @@ -110,7 +110,7 @@ class CallData final { public: explicit CallData(const MethodData<GrpcppService, CallTraits>& method_data) : wait_token_(method_data.service_data.wait_tokens.GetToken()), method_data_(method_data) { - UASSERT(method_data.method_id < method_data.service_data.metadata.method_full_names.size()); + UASSERT(method_data.method_id < GetMethodsCount(method_data.service_data.metadata)); } void operator()() && { diff --git a/grpc/src/ugrpc/client/client_factory.cpp b/grpc/src/ugrpc/client/client_factory.cpp index 62ae471c9cf7..2593163decea 100644 --- a/grpc/src/ugrpc/client/client_factory.cpp +++ b/grpc/src/ugrpc/client/client_factory.cpp @@ -13,14 +13,14 @@ ClientFactory::ClientFactory( ugrpc::impl::CompletionQueuePoolBase& completion_queues, ugrpc::impl::StatisticsStorage& statistics_storage, testsuite::GrpcControl& testsuite_grpc, - dynamic_config::Source source + dynamic_config::Source config_source ) : settings_(std::move(settings)), channel_task_processor_(channel_task_processor), mws_(mws), completion_queues_(completion_queues), client_statistics_storage_(statistics_storage), - config_source_(source), + config_source_(config_source), testsuite_grpc_(testsuite_grpc) { ugrpc::impl::SetupNativeLogging(); ugrpc::impl::UpdateNativeLogLevel(settings_.native_log_level); diff --git a/grpc/src/ugrpc/client/client_factory_settings.cpp b/grpc/src/ugrpc/client/client_factory_settings.cpp new file mode 100644 index 000000000000..cace149a3926 --- /dev/null +++ b/grpc/src/ugrpc/client/client_factory_settings.cpp @@ -0,0 +1,18 @@ +#include <userver/ugrpc/client/client_factory_settings.hpp> + +#include <userver/utils/algo.hpp> + +USERVER_NAMESPACE_BEGIN + +namespace ugrpc::client { + +std::shared_ptr<grpc::ChannelCredentials> +GetClientCredentials(const ClientFactorySettings& client_factory_settings, const std::string& client_name) { + return utils::FindOrDefault( + client_factory_settings.client_credentials, client_name, client_factory_settings.credentials + ); +} + +} // namespace ugrpc::client + +USERVER_NAMESPACE_END diff --git a/grpc/src/ugrpc/client/client_settings.cpp b/grpc/src/ugrpc/client/client_settings.cpp new file mode 100644 index 000000000000..0ac1f7b7ed4a --- /dev/null +++ b/grpc/src/ugrpc/client/client_settings.cpp @@ -0,0 +1,16 @@ +#include <userver/ugrpc/client/client_settings.hpp> + +#include <userver/utils/algo.hpp> + +USERVER_NAMESPACE_BEGIN + +namespace ugrpc::client { + +std::size_t +GetMethodChannelCount(const DedicatedMethodsConfig& dedicated_methods_config, std::string_view method_name) { + return utils::FindOrDefault(dedicated_methods_config, std::string{method_name}, std::size_t{0}); +} + +} // namespace ugrpc::client + +USERVER_NAMESPACE_END diff --git a/grpc/src/ugrpc/client/generic.cpp b/grpc/src/ugrpc/client/generic_client.cpp similarity index 97% rename from grpc/src/ugrpc/client/generic.cpp rename to grpc/src/ugrpc/client/generic_client.cpp index 7231478a6754..e99527906595 100644 --- a/grpc/src/ugrpc/client/generic.cpp +++ b/grpc/src/ugrpc/client/generic_client.cpp @@ -1,4 +1,4 @@ -#include <userver/ugrpc/client/generic.hpp> +#include <userver/ugrpc/client/generic_client.hpp> #include <grpcpp/generic/generic_stub.h> diff --git a/grpc/src/ugrpc/client/impl/call_params.cpp b/grpc/src/ugrpc/client/impl/call_params.cpp index 248a7ea46cba..4cc2ea1d12be 100644 --- a/grpc/src/ugrpc/client/impl/call_params.cpp +++ b/grpc/src/ugrpc/client/impl/call_params.cpp @@ -82,7 +82,7 @@ CallParams CreateCallParams( const Qos& qos ) { const auto& metadata = client_data.GetMetadata(); - const auto call_name = metadata.method_full_names[method_id]; + const auto call_name = GetMethodFullName(metadata, method_id); if (engine::current_task::ShouldCancel()) { throw RpcCancelledError(call_name, "RPC construction"); diff --git a/grpc/src/ugrpc/client/impl/client_data.cpp b/grpc/src/ugrpc/client/impl/client_data.cpp index eb0440afe177..056f2e100945 100644 --- a/grpc/src/ugrpc/client/impl/client_data.cpp +++ b/grpc/src/ugrpc/client/impl/client_data.cpp @@ -1,16 +1,9 @@ #include <userver/ugrpc/client/impl/client_data.hpp> -#include <fmt/format.h> -#include <fmt/ranges.h> -#include <grpcpp/create_channel.h> - -#include <userver/engine/async.hpp> #include <userver/utils/algo.hpp> #include <userver/utils/assert.hpp> #include <userver/utils/rand.hpp> -#include <userver/ugrpc/client/client_factory.hpp> -#include <userver/ugrpc/client/client_factory_settings.hpp> #include <userver/ugrpc/client/client_qos.hpp> #include <userver/ugrpc/client/impl/completion_queue_pool.hpp> #include <userver/ugrpc/impl/statistics_storage.hpp> @@ -19,24 +12,6 @@ USERVER_NAMESPACE_BEGIN namespace ugrpc::client::impl { -namespace { - -std::shared_ptr<grpc::ChannelCredentials> GetCredentails(const ClientDependencies& dependencies) { - return utils::FindOrDefault( - dependencies.settings.client_credentials, dependencies.client_name, dependencies.settings.credentials - ); -} - -bool MethodExists(const ugrpc::impl::StaticServiceMetadata& meta, std::string_view method_name) { - const auto& rpc_paths = meta.method_full_names; - return std::find_if(rpc_paths.begin(), rpc_paths.end(), [&method_name, &meta](const std::string_view full_path) { - const auto method = full_path.substr(meta.service_full_name.size() + 1); - return method == method_name; - }) != rpc_paths.end(); -} - -} // namespace - grpc::CompletionQueue& ClientData::NextQueue() const { return dependencies_.completion_queues.NextQueue(); } ugrpc::impl::MethodStatistics& ClientData::GetStatistics(std::size_t method_id) const { @@ -55,7 +30,7 @@ const ugrpc::impl::StaticServiceMetadata& ClientData::GetMetadata() const { const dynamic_config::Key<ClientQos>* ClientData::GetClientQos() const { return dependencies_.qos; } -const ClientData::StubPtr& ClientData::NextStubPtr(const utils::FixedArray<StubPtr>& stubs) const { +const ClientData::StubPtr& ClientData::NextStubPtr(const StubPool& stubs) const { return stubs[utils::RandRange(stubs.size())]; } @@ -68,46 +43,20 @@ std::size_t ClientData::GetDedicatedChannelCount(std::size_t method_id) const { return dedicated_stubs_[method_id].size(); } -std::shared_ptr<grpc::Channel> -ClientData::CreateChannelImpl(const ClientDependencies& dependencies, const grpc::string& endpoint) { - return engine::AsyncNoSpan( - dependencies.channel_task_processor, - grpc::CreateCustomChannel, - std::ref(endpoint), - dependencies.testsuite_grpc.IsTlsEnabled() ? GetCredentails(dependencies) - : grpc::InsecureChannelCredentials(), - std::ref(dependencies.settings.channel_args) - ) - .Get(); -} - -utils::FixedArray<std::shared_ptr<grpc::Channel>> ClientData::CreateChannels(const ClientDependencies& dependencies) { - const auto endpoint_string = ugrpc::impl::ToGrpcString(dependencies.endpoint); - return utils::GenerateFixedArray(dependencies.settings.channel_count, [&](std::size_t) { - return CreateChannelImpl(dependencies, endpoint_string); - }); +ChannelFactory ClientData::CreateChannelFactory(const ClientDependencies& dependencies) { + auto credentials = dependencies.testsuite_grpc.IsTlsEnabled() + ? GetClientCredentials(dependencies.client_factory_settings, dependencies.client_name) + : grpc::InsecureChannelCredentials(); + return ChannelFactory{ + dependencies.channel_task_processor, + dependencies.endpoint, + std::move(credentials), + dependencies.client_factory_settings.channel_args}; } -std::size_t ClientData::GetDedicatedChannelCountImpl( - const ClientDependencies& dependencies, - std::size_t method_id, - const ugrpc::impl::StaticServiceMetadata& meta -) { - const auto& rpc_paths = meta.method_full_names; - const auto& rpc_path = rpc_paths[method_id]; - const auto method_name = rpc_path.substr(meta.service_full_name.size() + 1); - UASSERT(!method_name.empty()); - - const auto& dedicated_methods_config = dependencies.dedicated_methods_config; - const auto it = dedicated_methods_config.find(std::string{method_name}); - if (it != dedicated_methods_config.end()) { - return it->second; - } - UINVARIANT( - MethodExists(meta, method_name), - fmt::format("Unknown method {}. Available methods: [{}]", method_name, fmt::join(rpc_paths, ", ")) - ); - return 0; +utils::FixedArray<std::shared_ptr<grpc::Channel>> +ClientData::CreateChannels(const ChannelFactory& channel_factory, std::size_t channel_count) { + return utils::GenerateFixedArray(channel_count, [&](std::size_t) { return channel_factory.CreateChannel(); }); } } // namespace ugrpc::client::impl diff --git a/grpc/src/ugrpc/client/simple_client_component.cpp b/grpc/src/ugrpc/client/simple_client_component.cpp index 7188e1b4da79..7b9c6ab43036 100644 --- a/grpc/src/ugrpc/client/simple_client_component.cpp +++ b/grpc/src/ugrpc/client/simple_client_component.cpp @@ -27,11 +27,11 @@ additionalProperties: false description: ClientFactoryComponent name to use for client creation dedicated-channel-counts: type: object - description: a map of method names to channel counts. Used for high-load methods + description: a map of rpc method names to channel counts. Used for high-load methods defaultDescription: '{}' additionalProperties: type: integer - description: a full path to service method, must be a string or integer + description: number of channels for this method minimum: 1 properties: {} )"); diff --git a/grpc/src/ugrpc/impl/statistics.cpp b/grpc/src/ugrpc/impl/statistics.cpp index 0e2eee4f972e..6aca768c1c49 100644 --- a/grpc/src/ugrpc/impl/statistics.cpp +++ b/grpc/src/ugrpc/impl/statistics.cpp @@ -184,7 +184,7 @@ ServiceStatistics::ServiceStatistics( StatisticsDomain domain, utils::statistics::StripedRateCounter& global_started ) - : metadata_(metadata), method_statistics_(metadata.method_full_names.size(), domain, global_started) {} + : metadata_(metadata), method_statistics_(GetMethodsCount(metadata), domain, global_started) {} MethodStatistics& ServiceStatistics::GetMethodStatistics(std::size_t method_id) { return method_statistics_[method_id]; diff --git a/grpc/tests/generic_client_test.cpp b/grpc/tests/generic_client_test.cpp index ffb805b898be..20ce9bf239ec 100644 --- a/grpc/tests/generic_client_test.cpp +++ b/grpc/tests/generic_client_test.cpp @@ -1,4 +1,4 @@ -#include <userver/ugrpc/client/generic.hpp> +#include <userver/ugrpc/client/generic_client.hpp> #include <cstdint> diff --git a/samples/grpc-generic-proxy/main.cpp b/samples/grpc-generic-proxy/main.cpp index 8e51855b1424..b744c99065b1 100644 --- a/samples/grpc-generic-proxy/main.cpp +++ b/samples/grpc-generic-proxy/main.cpp @@ -11,7 +11,7 @@ #include <userver/testsuite/testsuite_support.hpp> #include <userver/ugrpc/client/client_factory_component.hpp> #include <userver/ugrpc/client/common_component.hpp> -#include <userver/ugrpc/client/generic.hpp> +#include <userver/ugrpc/client/generic_client.hpp> #include <userver/ugrpc/client/middlewares/deadline_propagation/component.hpp> #include <userver/ugrpc/client/middlewares/log/component.hpp> #include <userver/ugrpc/client/simple_client_component.hpp> diff --git a/samples/grpc-generic-proxy/src/proxy_service.cpp b/samples/grpc-generic-proxy/src/proxy_service.cpp index a3e4a8a48eb7..bb68bd8508e9 100644 --- a/samples/grpc-generic-proxy/src/proxy_service.cpp +++ b/samples/grpc-generic-proxy/src/proxy_service.cpp @@ -6,7 +6,7 @@ #include <userver/components/component.hpp> #include <userver/ugrpc/byte_buffer_utils.hpp> -#include <userver/ugrpc/client/generic.hpp> +#include <userver/ugrpc/client/generic_client.hpp> #include <userver/ugrpc/client/simple_client_component.hpp> namespace samples {