Ejemplo n.º 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 = ResolveService <IEnumerable <ResolverFactory> >(options.ServiceProvider, 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}'.");
        }
Ejemplo n.º 2
0
        private void ResolveCredentials(GrpcChannelOptions channelOptions, out bool isSecure, out List <CallCredentials>?callCredentials)
        {
            if (channelOptions.Credentials != null)
            {
                var configurator = new DefaultChannelCredentialsConfigurator();
                // TODO(JamesNK): Remove nullable override after Grpc.Core.Api update
                channelOptions.Credentials.InternalPopulateConfiguration(configurator, null !);

                isSecure        = configurator.IsSecure ?? false;
                callCredentials = configurator.CallCredentials;

                ValidateChannelCredentials();
            }
            else
            {
                if (Address.Scheme == Uri.UriSchemeHttp)
                {
                    isSecure = false;
                }
                else if (Address.Scheme == Uri.UriSchemeHttps)
                {
                    isSecure = true;
                }
                else
                {
                    throw new InvalidOperationException($"Unable to determine the TLS configuration of the channel from address '{Address}'. " +
                                                        $"{nameof(GrpcChannelOptions)}.{nameof(GrpcChannelOptions.Credentials)} must be specified when the address doesn't have a 'http' or 'https' scheme. " +
                                                        "To call TLS endpoints, set credentials to 'new SslCredentials()'. " +
                                                        "To call non-TLS endpoints, set credentials to 'ChannelCredentials.Insecure'.");
                }
                callCredentials = null;
            }
        }
Ejemplo n.º 3
0
        internal GrpcChannel(Uri address, GrpcChannelOptions channelOptions) : base(address.Authority)
        {
            _methodInfoCache = new ConcurrentDictionary <IMethod, GrpcMethodInfo>();

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

            Address               = address;
            HttpClient            = channelOptions.HttpClient ?? CreateInternalHttpClient();
            SendMaxMessageSize    = channelOptions.MaxSendMessageSize;
            ReceiveMaxMessageSize = channelOptions.MaxReceiveMessageSize;
            CompressionProviders  = ResolveCompressionProviders(channelOptions.CompressionProviders);
            MessageAcceptEncoding = GrpcProtocolHelpers.GetMessageAcceptEncoding(CompressionProviders);
            LoggerFactory         = channelOptions.LoggerFactory ?? NullLoggerFactory.Instance;
            ThrowOperationCanceledOnCancellation = channelOptions.ThrowOperationCanceledOnCancellation;
            _createMethodInfoFunc = CreateMethodInfo;

            if (channelOptions.Credentials != null)
            {
                var configurator = new DefaultChannelCredentialsConfigurator();
                channelOptions.Credentials.InternalPopulateConfiguration(configurator, null);

                IsSecure        = configurator.IsSecure;
                CallCredentials = configurator.CallCredentials;

                ValidateChannelCredentials();
            }
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        private static HttpHandlerType CalculateHandlerType(GrpcChannelOptions channelOptions)
        {
            if (channelOptions.HttpHandler == null)
            {
                // No way to know what handler a HttpClient is using so assume custom.
                return(channelOptions.HttpClient == null
                    ? HttpHandlerType.SocketsHttpHandler
                    : HttpHandlerType.Custom);
            }

            return(HttpRequestHelpers.CalculateHandlerType(channelOptions.HttpHandler));
        }
Ejemplo n.º 6
0
        private static HttpHandlerContext CalculateHandlerContext(GrpcChannelOptions channelOptions)
        {
            if (channelOptions.HttpHandler == null)
            {
                // No way to know what handler a HttpClient is using so assume custom.
                var type = channelOptions.HttpClient == null
                    ? HttpHandlerType.SocketsHttpHandler
                    : HttpHandlerType.Custom;

                return(new HttpHandlerContext(type));
            }

            if (HttpRequestHelpers.HasHttpHandlerType(channelOptions.HttpHandler, "System.Net.Http.WinHttpHandler"))
            {
                return(new HttpHandlerContext(HttpHandlerType.WinHttpHandler));
            }
            if (HttpRequestHelpers.HasHttpHandlerType(channelOptions.HttpHandler, "System.Net.Http.SocketsHttpHandler"))
            {
                HttpHandlerType type;
                TimeSpan?       connectTimeout;

#if NET5_0_OR_GREATER
                var socketsHttpHandler = HttpRequestHelpers.GetHttpHandlerType <SocketsHttpHandler>(channelOptions.HttpHandler) !;

                type           = HttpHandlerType.SocketsHttpHandler;
                connectTimeout = socketsHttpHandler.ConnectTimeout;

                // Check if the SocketsHttpHandler is being shared by channels.
                // It has already been setup by another channel (i.e. ConnectCallback is set) then
                // additional channels can use advanced connectivity features.
                if (!BalancerHttpHandler.IsSocketsHttpHandlerSetup(socketsHttpHandler))
                {
                    // Someone has already configured the handler callback.
                    // This channel can't support advanced connectivity features.
                    if (socketsHttpHandler.ConnectCallback != null)
                    {
                        type           = HttpHandlerType.Custom;
                        connectTimeout = null;
                    }
                }
#else
                type           = HttpHandlerType.SocketsHttpHandler;
                connectTimeout = null;
#endif
                return(new HttpHandlerContext(type, connectTimeout));
            }
            if (HttpRequestHelpers.GetHttpHandlerType <HttpClientHandler>(channelOptions.HttpHandler) != null)
            {
                return(new HttpHandlerContext(HttpHandlerType.HttpClientHandler));
            }

            return(new HttpHandlerContext(HttpHandlerType.Custom));
        }
Ejemplo n.º 7
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;
            HttpInvoker = channelOptions.HttpClient ?? CreateInternalHttpInvoker(channelOptions.HttpHandler);
            IsWinHttp   = channelOptions.HttpHandler != null?HttpHandlerFactory.HasHttpHandlerType(channelOptions.HttpHandler, "System.Net.Http.WinHttpHandler") : false;

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

                _serviceConfigMethods = CreateServiceConfigMethods(serviceConfig);
                _random = new Random();
            }

            if (channelOptions.Credentials != null)
            {
                var configurator = new DefaultChannelCredentialsConfigurator();
                channelOptions.Credentials.InternalPopulateConfiguration(configurator, null);

                IsSecure        = configurator.IsSecure;
                CallCredentials = configurator.CallCredentials;

                ValidateChannelCredentials();
            }

            if (!string.IsNullOrEmpty(Address.PathAndQuery) && Address.PathAndQuery != "/")
            {
                Log.AddressPathUnused(Logger, Address.OriginalString);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Creates a <see cref="GrpcChannel"/> for the specified address and configuration options.
        /// </summary>
        /// <param name="address">The address the channel will use.</param>
        /// <param name="channelOptions">The channel configuration options.</param>
        /// <returns>A new instance of <see cref="GrpcChannel"/>.</returns>
        public static GrpcChannel ForAddress(Uri address, GrpcChannelOptions channelOptions)
        {
            if (address == null)
            {
                throw new ArgumentNullException(nameof(address));
            }

            if (channelOptions == null)
            {
                throw new ArgumentNullException(nameof(channelOptions));
            }

            return(new GrpcChannel(address, channelOptions));
        }
Ejemplo n.º 9
0
        public void GlobalSetup()
        {
            var definitionsProvider = new RpcServiceDefinitionsBuilder();

            switch (this.ConnectionType)
            {
            case RpcConnectionType.Grpc:
                this.server = new GrpcCore.Server
                {
                    Services = { SimpleService.BindService(new GrpcSimpleService()) },
                    Ports    = { new GrpcCore.ServerPort("localhost", 50051, GrpcCore.ServerCredentials.Insecure) }
                };
                this.server.Start();

                this.channel       = new GrpcCore.Channel("127.0.0.1:50051", GrpcCore.ChannelCredentials.Insecure);
                this.clientService = new SimpleService.SimpleServiceClient(this.channel);
                break;

#if COREFX
            case RpcConnectionType.NetGrpc:
                this.host = CreateNetGrpcHost();
                host.Start();


                var handler = new System.Net.Http.HttpClientHandler();
                handler.ServerCertificateCustomValidationCallback =
                    (httpRequestMessage, cert, cetChain, policyErrors) =>
                {
                    return(true);
                };
                var channelOptions = new GrpcNet.Client.GrpcChannelOptions()
                {
                    HttpClient        = new System.Net.Http.HttpClient(handler),
                    DisposeHttpClient = true
                };

                this.channel       = GrpcChannel.ForAddress("https://localhost:50051", channelOptions);
                this.clientService = new SimpleService.SimpleServiceClient(channel);
                break;
#endif
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Creates a <see cref="GrpcChannel"/> for the specified address and configuration options.
        /// </summary>
        /// <param name="address">The address the channel will use.</param>
        /// <param name="channelOptions">The channel configuration options.</param>
        /// <returns>A new instance of <see cref="GrpcChannel"/>.</returns>
        public static GrpcChannel ForAddress(Uri address, GrpcChannelOptions channelOptions)
        {
            if (address == null)
            {
                throw new ArgumentNullException(nameof(address));
            }

            if (channelOptions == null)
            {
                throw new ArgumentNullException(nameof(channelOptions));
            }

            if (channelOptions.HttpClient != null && channelOptions.HttpHandler != null)
            {
                throw new ArgumentException($"{nameof(GrpcChannelOptions.HttpClient)} and {nameof(GrpcChannelOptions.HttpHandler)} have been configured. " +
                                            $"Only one HTTP caller can be specified.");
            }

            return(new GrpcChannel(address, channelOptions));
        }
Ejemplo n.º 11
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 ?? ResolveService <ILoggerFactory>(channelOptions.ServiceProvider, NullLoggerFactory.Instance);
            RandomGenerator = ResolveService <IRandomGenerator>(channelOptions.ServiceProvider, new RandomGenerator());
            HttpHandlerType = CalculateHandlerType(channelOptions);

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

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

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

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

            ConnectionManager = new ConnectionManager(
                resolver,
                channelOptions.DisableResolverServiceConfig,
                LoggerFactory,
                SubchannelTransportFactory,
                ResolveLoadBalancerFactories(channelOptions.ServiceProvider));
            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;
            _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);
            }
        }
Ejemplo n.º 12
0
 /// <summary>
 /// Creates a <see cref="GrpcChannel"/> for the specified address and configuration options.
 /// </summary>
 /// <param name="address">The address the channel will use.</param>
 /// <param name="channelOptions">The channel configuration options.</param>
 /// <returns>A new instance of <see cref="GrpcChannel"/>.</returns>
 public static GrpcChannel ForAddress(string address, GrpcChannelOptions channelOptions)
 {
     return(ForAddress(new Uri(address), channelOptions));
 }
        public static void CreateChannel(string address, Action <GrpcChannel, Metadata> action, Action <RpcException> exAction = null, Action <ChannelCustomerOptions> customerOptions = null, GrpcChannelOptions options = null)
        {
            var headers    = new Metadata();
            var cusOptions = new ChannelCustomerOptions();

            if (customerOptions != null)
            {
                customerOptions(cusOptions);
            }

            var token = cusOptions.GetToken();

            if (!string.IsNullOrWhiteSpace(token))
            {
                headers.Add($"{AuthUtil.AUTH_KEY}", token.AddBearerToken());
            }
            var eventId = cusOptions.GetEventId();

            if (!string.IsNullOrWhiteSpace(eventId))
            {
                headers.Add(App.EVENT_ID_KEY, eventId);
            }

            var channel = options == null?GrpcChannel.ForAddress(address) : GrpcChannel.ForAddress(address, options);

            ExecCallBusiness(address, cusOptions, channel, headers, eventId, action, exAction);
        }
        /// <summary>
        /// 获取策略中的GRpc客户端
        /// </summary>
        /// <typeparam name="GRpcClientT">GRpc客户端类型</typeparam>
        /// <param name="serviceName">服务名</param>
        /// <param name="createGRpcClient">创建GRpc客户端</param>
        /// <param name="action">回调业务处理方法</param>
        /// <param name="exAction">发生异常回调,如果为null,则不会捕获异常</param>
        /// <param name="customerOptions">自定义选项配置</param>
        /// <param name="options">grpc选项配置</param>
        /// <returns>GRpc客户端</returns>
        public static GRpcClientT GetGRpcClientFormStrategy <GRpcClientT>(string serviceName, Func <GrpcChannel, GRpcClientT> createGRpcClient, Action <GRpcClientT, Metadata> action, Action <RpcException> exAction = null, Action <ChannelCustomerOptions> customerOptions = null, GrpcChannelOptions options = null)
            where GRpcClientT : ClientBase <GRpcClientT>
        {
            var grpcChannel = App.GetServiceFromInstance <IGRpcChannel>();
            var channel     = grpcChannel.BuilderAsync(serviceName, options).Result;
            var client      = createGRpcClient(channel);

            ExecGRpcClient(client, action, exAction, customerOptions);

            return(client);
        }