日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用zipKin构建NetCore分布式链路跟踪

發布時間:2023/12/4 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用zipKin构建NetCore分布式链路跟踪 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文主要講解使用ZipKin構建NetCore分布式鏈路跟蹤


場景

因為最近公司業務量增加,而項目也需要增大部署數量,K8S中Pod基本都擴容了一倍,新增了若干物理機,部分物理機網絡通信存在問題,導致部分請求打入有問題的物理機時總會出現超時的情況,由于之前系統中沒有使用鏈路跟蹤,導致排查問題比較慢,所以就去研究了市面上的鏈路框架,結果發現了ZipKin這款比較輕量級的鏈路跟蹤框架。


實例代碼

本文日志系統采用Exceplesstion
示例代碼請求鏈路為SimpleZipkin(網關服務)--->WebApi(Api服務)--->OrderApi(訂單服務)
首先創建公用類庫,引用以下包(本文以1.5.0版本為例)
如果部署Zipkin使用的是Mysql作為存儲,切記Mysql版本不要高于8.0,Zipkin暫不支持8.0的版本

zipkin4net zipkin4net.middleware.aspnetcore

創建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 name="logger"></param>/// <param name="message"></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 name="logger"></param>/// <param name="message"></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 name="logger"></param>/// <param name="message"></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 name="logger"></param>/// <param name="message"></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 name="logger"></param>/// <param name="message"></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>();});}

接下來在Startup中引入ZipKin

public void ConfigureServices(IServiceCollection services){// 注入Rpc//AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);//services.AddGrpcClient<HelloServer.HelloServerClient>((p, o) =>//{// o.Address = new Uri("http://127.0.0.1:3848");//});//.AddHttpMessageHandler(provider => TracingHandler.WithoutInnerHandler("RpcService"));services.AddControllers();services.AddZipKin();services.AddSingleton<IDiagnosticSource, HttpDiagnosticSourceDemo>();services.AddHttpClient("webApi", client => { client.BaseAddress = new Uri($"http://localhost:5001"); });services.AddSwaggerGen(c =>{c.SwaggerDoc("v1", new OpenApiInfo { Title = "SimpleZipKin", Version = "v1" });});}public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory,IHostApplicationLifetime lifetime){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();app.UseSwagger();app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "SimpleZipkin v1"));}Configuration.GetSection("ExceptionLess").Bind(ExceptionlessClient.Default.Configuration);ExceptionlessClient.Default.Configuration.SetDefaultMinLogLevel(Exceptionless.Logging.LogLevel.Debug);app.UseZipKin(lifetime, loggerFactory, "SimpleZip", "http://127.0.0.1:9411");//SimpleZip修改為對應的應用名稱,127.0.0.1地址切換為自己的zipkin地址 app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints => { endpoints.MapControllers(); });}

接下來創建對應的Controller

[Route("/api/Home")]public class HomeController : Controller{private readonly IHttpClientFactory _httpClientFactory;private readonly ILogger _logger;/// <summary>/// 構造函數/// </summary>/// <param name="httpClientFactory"></param>/// <param name="logger"></param>public HomeController(IHttpClientFactory httpClientFactory, ILogger<HomeController> logger){_httpClientFactory = httpClientFactory;//_helloServerClient = helloServerClient;_logger = logger;}[HttpGet("GetZipKin")]public async Task<string> GetZipKin(){_logger.InformationToException($@"這里是SimpleZipKinApi");var httpClient = _httpClientFactory.CreateClient("webApi");var httpResult = await httpClient.GetAsync($"api/order/getorder");var result = await httpResult.Content.ReadAsStringAsync();return result;} }

最后在appsettings.json中加入對應的Exceplesstionless配置

"ExceptionLess": {"ApiKey": "****************************","ServerUrl": "http://127.0.0.1:5000"}

OrderApi、WebApi如法炮制,修改對應的請求鏈路信息

接下來我們使用DiagnosticAdapter做鏈路記載,在公共類庫中創建HttpDiagnosticListener類
DiagnosticSource是Runtime層提供,應用層可以通過它與系統集成、事件日志、以及性能計數器進行交互。
DiagnosticSource官方介紹:https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.diagnosticsource?view=net-5.0
關于DiagnosticSource設計參考原有yi念之間大佬的文章:https://www.cnblogs.com/wucy/p/13532534.html

public class HttpDiagnosticSourceDemo : IDiagnosticSourceDemo{public string DiagnosticName => "HttpDiagnosticSourceDemo";private ClientTrace _clientTrace;private readonly IInjector<HttpHeaders> _injector = Propagations.B3String.Injector<HttpHeaders>((carrier, key, value) => carrier.Add(key, value));[DiagnosticName("System.Net.Http.Request")]public void HttpRequest(HttpRequestMessage request){_clientTrace = new ClientTrace("simpleZipKin", request.Method.Method);if (_clientTrace.Trace != null){_injector.Inject(_clientTrace.Trace.CurrentSpan, request.Headers);}}[DiagnosticName("System.Net.Http.Response")]public void HttpResponse(HttpResponseMessage response){if (_clientTrace.Trace != null){_clientTrace.AddAnnotation(Annotations.Tag(zipkinCoreConstants.HTTP_PATH, response.RequestMessage.RequestUri.LocalPath));_clientTrace.AddAnnotation(Annotations.Tag(zipkinCoreConstants.HTTP_METHOD, response.RequestMessage.Method.Method));_clientTrace.AddAnnotation(Annotations.Tag(zipkinCoreConstants.HTTP_HOST, response.RequestMessage.RequestUri.Host));if (!response.IsSuccessStatusCode){_clientTrace.AddAnnotation(Annotations.Tag(zipkinCoreConstants.HTTP_STATUS_CODE, ((int)response.StatusCode).ToString()));}}}[DiagnosticName("System.Net.Http.Exception")]public void HttpException(HttpRequestMessage request, Exception exception){}}

IDiagnosticSourceDemo接口信息如下:

public interface IDiagnosticSourceDemo{string DiagnosticName { get; }}

HttpDiagnosticSourceObserver方法如下:

public class HttpDiagnosticSourceObserver : IObserver<DiagnosticListener>{private IEnumerable<IDiagnosticSourceDemo> _diagnosticSourceDemo;public HttpDiagnosticSourceObserver (IEnumerable<IDiagnosticSourceDemo> diagnosticSourceDemo){_diagnosticSourceDemo= diagnosticSourceDemo;}public void OnCompleted(){}public void OnError(Exception error){}public void OnNext(DiagnosticListener listener){var diagnosticSource= _diagnosticSourceDemo.FirstOrDefault(i => i.DiagnosticName == listener.Name);if (traceDiagnostic != null){//適配訂閱listener.SubscribeWithAdapter(diagnosticSource);}}}

最終運行結果如下:
Zipkin為:

Exceplesstion日志記錄信息為

通過Exceptionless記錄的環境信息也能將對應的機器定位

參考

本文引用文章連接如下:
DiagnosticSource官方介紹:https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.diagnosticsource?view=net-5.0
DiagnosticSource參考連接:https://www.cnblogs.com/wucy/p/13532534.html
? ? ? ? ? ? ? ? ? ?https://sudonull.com/post/3671-Using-the-DiagnosticSource-in-NET-Core-Theory
? ? ? ? ? ? ? ? ? ?https://andrewlock.net/logging-using-diagnosticsource-in-asp-net-core/
docker部署Zipkin:https://www.cnblogs.com/binz/p/12658020.html
docekr部署exceptionless:https://www.cnblogs.com/edisonchou/p/exceptionless_v5_deployment_introduction.html

總結

以上是生活随笔為你收集整理的使用zipKin构建NetCore分布式链路跟踪的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。