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}'."); }
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; } }
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(); } }
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); }
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)); }
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)); }
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); } }
/// <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)); }
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 } }
/// <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)); }
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); } }
/// <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); }