using Grpc.Core; using Grpc.Extension.Abstract; using Grpc.Extension.Abstract.Discovery; using Grpc.Extension.Client.Interceptors; using Grpc.Extension.Client.Internal; using Grpc.Extension.Client.LoadBalancer; using Grpc.Extension.Client.Model; using Grpc.Extension.Common; using Grpc.Extension.Discovery; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenTracing; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace Grpc.Extension.Client { /// /// ServiceCollectionExtensions /// public static class ServiceCollectionExtensions { /// /// 添加GrpcClient扩展 /// /// /// /// public static IServiceCollection AddGrpcClientExtensions(this IServiceCollection services, IConfiguration conf) { //注入配制 services.Configure(conf.GetSection("GrpcClient")); //GrpcClientApp services.AddSingleton(); //添加客户端中间件的CallInvoker services.AddSingleton(); services.AddSingleton(); //添加Channel的Manager services.AddSingleton(); services.AddSingleton(); //默认使用轮询负载策略,在外面可以注入其它策略 if (!services.Any(p => p.ServiceType == typeof(ILoadBalancer))) { services.AddSingleton(); } //默认使用consul服务注册,服务发现,在外面可以注入其它策略 if (!services.Any(p => p.ServiceType == typeof(IServiceRegister))) { services.AddConsulDiscovery(); } //添加缓存 services.AddMemoryCache(); //添加客户端中间件 services.AddClientCallTimeout(); services.AddClientMonitor(); //Jaeger services.AddClientJaeger(conf); return services; } /// /// 添加GrpcClient到Discovery,生成元数据 /// /// /// /// Discovery上客户端服务名字 /// Discovery的服务器地址 /// ChannelOption /// public static IServiceCollection AddGrpcClient(this IServiceCollection services, string discoveryServiceName, string discoveryUrl = "", IEnumerable channelOptions = null) where T : ClientBase { services.AddSingleton(); var channelConfig = new ChannelConfig { DiscoveryUrl = discoveryUrl, DiscoveryServiceName = discoveryServiceName, ChannelOptions = channelOptions }; var bindFlags = BindingFlags.Static | BindingFlags.NonPublic; channelConfig.GrpcServiceName = typeof(T).DeclaringType.GetFieldValue("__ServiceName", bindFlags); ChannelPool.Configs.Add(channelConfig); return services; } /// /// 添加GrpcClient到Discovery,生成元数据 /// /// /// /// Discovery上客户端服务名字 /// Discovery的服务器地址 /// ChannelOption /// public static IServiceCollection AddGrpcClientByDiscovery(this IServiceCollection services, string discoveryServiceName, string discoveryUrl = "", IEnumerable channelOptions = null) where T : ClientBase { services.AddGrpcClient(discoveryServiceName, discoveryUrl, channelOptions); return services; } /// /// 添加客户端日志监控Interceptor /// /// /// private static IServiceCollection AddClientMonitor(this IServiceCollection services) { services.AddClientInterceptor(); return services; } /// /// 添加客户端超时Interceptor /// /// /// private static IServiceCollection AddClientCallTimeout(this IServiceCollection services) { services.AddSingleton(sp => { var options = sp.GetService>().Value; return new ClientCallTimeout(options.GrpcCallTimeOut); }); return services; } /// /// 添加Jaeger /// /// /// /// public static IServiceCollection AddClientJaeger(this IServiceCollection services, IConfiguration conf) { //读取Jaeger配制 var key = conf["GrpcServer:ServiceAddress"] != null ? "GrpcServer" : "GrpcClient"; var jaegerOptions = conf.GetSection($"{key}:Jaeger").Get(); if (jaegerOptions == null || jaegerOptions.Enable == false) return services; //jaeger if (!services.Any(p => p.ServiceType == typeof(ITracer))) { services.AddSingleton(sp => { var options = sp.GetService>().Value; var tracer = new Jaeger.Tracer.Builder(options.Jaeger.ServiceName) .WithLoggerFactory(sp.GetService()) .WithSampler(new Jaeger.Samplers.ConstSampler(true)) .WithReporter(new Jaeger.Reporters.RemoteReporter.Builder() .WithFlushInterval(TimeSpan.FromSeconds(5)) .WithMaxQueueSize(5) .WithSender(new Jaeger.Senders.UdpSender(jaegerOptions.AgentIp, jaegerOptions.AgentPort, 1024 * 5)).Build()) .Build(); return tracer; }); } //添加jaeger中间件 services.AddClientInterceptor(); return services; } /// /// 添加客户端Interceptor /// /// /// /// public static IServiceCollection AddClientInterceptor(this IServiceCollection services) where T : ClientInterceptor { services.AddSingleton(); return services; } } }