コード例 #1
0
        private ResolverFactory GetResolverFactory(GrpcChannelOptions options)
        {
            // Special case http and https schemes. These schemes don't use a dynamic resolver. An http/https
            // address is always just one address and that is enabled using the static resolver.
            //
            // Even with just one address we still want to use the load balancing infrastructure. This enables
            // the connectivity APIs on channel like GrpcChannel.State and GrpcChannel.WaitForStateChanged.
            if (IsHttpOrHttpsAddress())
            {
                return(new StaticResolverFactory(uri => new[] { new BalancerAddress(Address.Host, Address.Port) }));
            }

            var factories = options.ResolveService <IEnumerable <ResolverFactory> >(Array.Empty <ResolverFactory>());

            factories = factories.Union(ResolverFactory.KnownLoadResolverFactories);

            foreach (var factory in factories)
            {
                if (string.Equals(factory.Name, Address.Scheme, StringComparison.OrdinalIgnoreCase))
                {
                    return(factory);
                }
            }

            throw new InvalidOperationException($"No address resolver configured for the scheme '{Address.Scheme}'.");
        }
コード例 #2
0
        private LoadBalancerFactory[] ResolveLoadBalancerFactories(GrpcChannelOptions channelOptions)
        {
            var serviceFactories = channelOptions.ResolveService <IEnumerable <LoadBalancerFactory>?>(defaultValue: null);

            if (serviceFactories != null)
            {
                return(serviceFactories.Union(LoadBalancerFactory.KnownLoadBalancerFactories).ToArray());
            }

            return(LoadBalancerFactory.KnownLoadBalancerFactories);
        }
コード例 #3
0
        internal GrpcChannel(Uri address, GrpcChannelOptions channelOptions) : base(address.Authority)
        {
            _lock            = new object();
            _methodInfoCache = new ConcurrentDictionary <IMethod, GrpcMethodInfo>();

            // Dispose the HTTP client/handler if...
            //   1. No client/handler was specified and so the channel created the client itself
            //   2. User has specified a client/handler and set DisposeHttpClient to true
            _shouldDisposeHttpClient = (channelOptions.HttpClient == null && channelOptions.HttpHandler == null) ||
                                       channelOptions.DisposeHttpClient;

            Address         = address;
            LoggerFactory   = channelOptions.LoggerFactory ?? channelOptions.ResolveService <ILoggerFactory>(NullLoggerFactory.Instance);
            RandomGenerator = channelOptions.ResolveService <IRandomGenerator>(new RandomGenerator());
            HttpHandlerType = CalculateHandlerType(channelOptions);

#if SUPPORT_LOAD_BALANCING
            InitialReconnectBackoff = channelOptions.InitialReconnectBackoff;
            MaxReconnectBackoff     = channelOptions.MaxReconnectBackoff;

            var resolverFactory = GetResolverFactory(channelOptions);
            ResolveCredentials(channelOptions, out _isSecure, out _callCredentials);

            SubchannelTransportFactory = channelOptions.ResolveService <ISubchannelTransportFactory>(new SubChannelTransportFactory(this));

            if (!IsHttpOrHttpsAddress() || channelOptions.ServiceConfig?.LoadBalancingConfigs.Count > 0)
            {
                ValidateHttpHandlerSupportsConnectivity();
            }

            var defaultPort = IsSecure ? 443 : 80;
            var resolver    = resolverFactory.Create(new ResolverOptions(Address, defaultPort, LoggerFactory, channelOptions));

            ConnectionManager = new ConnectionManager(
                resolver,
                channelOptions.DisableResolverServiceConfig,
                LoggerFactory,
                channelOptions.ResolveService <IBackoffPolicyFactory>(new ExponentialBackoffPolicyFactory(RandomGenerator, InitialReconnectBackoff, MaxReconnectBackoff)),
                SubchannelTransportFactory,
                ResolveLoadBalancerFactories(channelOptions));
            ConnectionManager.ConfigureBalancer(c => new ChildHandlerLoadBalancer(
                                                    c,
                                                    channelOptions.ServiceConfig,
                                                    ConnectionManager));
#else
            if (string.IsNullOrEmpty(address.Host))
            {
                throw new ArgumentException($"Address '{address.OriginalString}' doesn't have a host. Address should include a scheme, host, and optional port. For example, 'https://localhost:5001'.");
            }
            ResolveCredentials(channelOptions, out _isSecure, out _callCredentials);
#endif

            HttpInvoker               = channelOptions.HttpClient ?? CreateInternalHttpInvoker(channelOptions.HttpHandler);
            SendMaxMessageSize        = channelOptions.MaxSendMessageSize;
            ReceiveMaxMessageSize     = channelOptions.MaxReceiveMessageSize;
            MaxRetryAttempts          = channelOptions.MaxRetryAttempts;
            MaxRetryBufferSize        = channelOptions.MaxRetryBufferSize;
            MaxRetryBufferPerCallSize = channelOptions.MaxRetryBufferPerCallSize;
            CompressionProviders      = ResolveCompressionProviders(channelOptions.CompressionProviders);
            MessageAcceptEncoding     = GrpcProtocolHelpers.GetMessageAcceptEncoding(CompressionProviders);
            Logger = LoggerFactory.CreateLogger <GrpcChannel>();
            ThrowOperationCanceledOnCancellation    = channelOptions.ThrowOperationCanceledOnCancellation;
            UnsafeUseInsecureChannelCallCredentials = channelOptions.UnsafeUseInsecureChannelCallCredentials;
            _createMethodInfoFunc = CreateMethodInfo;
            ActiveCalls           = new HashSet <IDisposable>();
            if (channelOptions.ServiceConfig is { } serviceConfig)
            {
                RetryThrottling = serviceConfig.RetryThrottling != null?CreateChannelRetryThrottling(serviceConfig.RetryThrottling) : null;

                _serviceConfigMethods = CreateServiceConfigMethods(serviceConfig);
            }

            // Non-HTTP addresses (e.g. dns:///custom-hostname) usually specify a path instead of an authority.
            // Only log about a path being present if HTTP or HTTPS.
            if (!string.IsNullOrEmpty(Address.PathAndQuery) &&
                Address.PathAndQuery != "/" &&
                (Address.Scheme == Uri.UriSchemeHttps || Address.Scheme == Uri.UriSchemeHttp))
            {
                Log.AddressPathUnused(Logger, Address.OriginalString);
            }
        }