因为最近公司业务量增加,而项目也需要增大部署数量,K8S中Pod基本都扩容了一倍,新增了若干物理机,部分物理机网络通信存在问题,导致部分请求打入有问题的物理机时总会出现超时的情况,由于之前系统中没有使用链路跟踪,导致排查问题比较慢,所以就去研究了市面上的链路框架,结果发现了ZipKin这款比较轻量级的链路跟踪框架。
实例代码本文日志系统采用Exceplesstion
示例代码请求链路为SimpleZipkin(网关服务)--->WebApi(Api服务)--->OrderApi(订单服务)
首先创建公用类库,引用以下包(本文以1.5.0版本为例)
如果部署Zipkin使用的是Mysql作为存储,切记Mysql版本不要高于8.0,Zipkin暂不支持8.0的版本
创建ZipKin帮助类
public static class ZipKinExtensions { public static IServiceCollection AddZipKin(this IServiceCollection services) { return services.AddSingleton<HttpDiagnosticSourceObserver >(); } public static IApplicationBuilder UseZipKin(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ILoggerFactory loggerFactory, string serviceName, string zipKinUrl) { DiagnosticListener.AllListeners.Subscribe(app?.ApplicationServices?.GetService<TraceObserver>()); lifetime.ApplicationStarted.Register(() => { TraceManager.SamplingRate = 1.0f;//记录数据密度,1.0代表全部记录 var logger = new TracingLogger(loggerFactory, "zipkin4net"); var httpSender = new HttpZipkinSender(zipKinUrl, "application/json"); var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer(), new Statistics()); var consoleTracer = new zipkin4net.Tracers.ConsoleTracer(); TraceManager.RegisterTracer(tracer); TraceManager.RegisterTracer(consoleTracer); TraceManager.Start(logger); }); lifetime.ApplicationStopped.Register(() => TraceManager.Stop()); app.UseTracing(serviceName);//这边的名字可自定义 return app; } }Exceptionless帮助类
/// <summary> /// 日志扩展类 /// </summary> public static class LogHelper { /// <summary> /// 记录Info日志 /// </summary> /// <param></param> /// <param></param> public static void InformationToException(this ILogger logger, string message) { var tranceId = Trace.Current?.CurrentSpan.TraceId.ToString("x16"); logger.LogInformation($@"tranceId={tranceId},日志主体为:{message}"); } /// <summary> /// 记录Debug日志 /// </summary> /// <param></param> /// <param></param> public static void DebugToException(this ILogger logger, string message) { var tranceId = Trace.Current?.CurrentSpan.TraceId.ToString("x16"); logger.LogDebug($@"tranceId={tranceId},日志主体为:{message}"); } /// <summary> /// 记录错误日志 /// </summary> /// <param></param> /// <param></param> public static void ErrorToException(this ILogger logger, string message) { var tranceId = Trace.Current?.CurrentSpan.TraceId.ToString("x16"); logger.LogError($@"tranceId={tranceId},日志主体为:{message}"); } /// <summary> /// 记录追踪日志 /// </summary> /// <param></param> /// <param></param> public static void TraceToException(this ILogger logger, string message) { var tranceId = Trace.Current?.CurrentSpan.TraceId.ToString("x16"); logger.LogTrace($@"tranceId={tranceId},日志主体为:{message}"); } /// <summary> /// 记录警告日志 /// </summary> /// <param></param> /// <param></param> public static void WarningToException(this ILogger logger, string message) { var tranceId = Trace.Current?.CurrentSpan.TraceId.ToString("x16"); logger.LogWarning($@"tranceId={tranceId},日志主体为:{message}"); } }接下来创建SimpleZipkin、WebApi、OrderApi等项目(因为结构一致,所以本文只创建一个),首先引用Exceplesstion
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureLogging((hostContext, configLogging) => { configLogging.AddConfiguration(hostContext.Configuration.GetSection("Logging")); configLogging.AddConsole(); configLogging.AddDebug(); configLogging.AddExceptionless(); ExceptionlessClient.Default.Configuration.SetDefaultMinLogLevel(Exceptionless.Logging.LogLevel.Debug); configLogging.SetMinimumLevel(LogLevel.Debug); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }