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;
}
}
}