zipkin链路追踪

一、部署:

服务器:192.168.17.82

一:执行命令:

1、docker pull openzipkin/zipkin
2、docker run -d -p 9411:9411 openzipkin/zipkin
–STORAGE_TYPE=elasticsearch
–ES_HOSTS=http://192.168.16.185:9200
–ES_HTTP_LOGGING=BASIC
–ES_USERNAME=elastic
–ES_PASSWORD=159753
–ES_MAX_SPAN_AGE=7d

3、访问:http://192.168.17.82:9411/

二、net6集成Zipkin

1、net6项目中首先需要引入如下依赖包 zipkin4net 1.5.0、zipkin4net.middleware.aspnetcore 1.5.0
2、项目添加zipkin文件夹,并添加如下4个类,

using skywalking_test.zipkin;
using System.Net.Http.Headers;
using zipkin4net.Propagation;
using zipkin4net.Tracers.Zipkin.Thrift;
using zipkin4net;
using Microsoft.Extensions.DiagnosticAdapter;

namespace skywalking_test.zipkin
{
    public class HttpDiagnosticListener : ITraceDiagnosticListener
    {
        public string DiagnosticName => "HttpHandlerDiagnosticListener";

        private ClientTrace clientTrace;
        private readonly IInjector<HttpHeaders> _injector = Propagations.B3String.Injector<HttpHeaders>((carrier, key, value) => carrier.Add(key, value));
        private readonly IConfiguration _configuration;
        private ZipkinOptions _zipkinOptions = new ZipkinOptions();

        public HttpDiagnosticListener(IConfiguration configuration)
        {
            _configuration = configuration;
            _configuration.GetRequiredSection("Zipkin").Bind(_zipkinOptions);
        }

        [DiagnosticName("System.Net.Http.Request")]
        public void HttpRequest(HttpRequestMessage request)
        {
            clientTrace = new ClientTrace(_zipkinOptions.ServiceName, request.Method.Method);
            if (clientTrace.Trace != null && request != null)
            {
                _injector.Inject(clientTrace.Trace.CurrentSpan, request.Headers);
            }
        }

        [DiagnosticName("System.Net.Http.Response")]
        public void HttpResponse(HttpResponseMessage response)
        {
            if (clientTrace.Trace != null && response != 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)
        {
        }
    }
}
namespace skywalking_test.zipkin
{
    public interface ITraceDiagnosticListener
    {
        string DiagnosticName { get; }
    }
}
using System.Diagnostics;

namespace skywalking_test.zipkin
{
    public class TraceObserver : IObserver<DiagnosticListener>
    {
        private IEnumerable<ITraceDiagnosticListener> _traceDiagnostics;
        public TraceObserver(IEnumerable<ITraceDiagnosticListener> traceDiagnostics)
        {
            _traceDiagnostics = traceDiagnostics;
        }

        public void OnCompleted()
        {
        }

        public void OnError(Exception error)
        {
        }

        public void OnNext(DiagnosticListener listener)
        {
            var traceDiagnostic = _traceDiagnostics.FirstOrDefault(i => i.DiagnosticName == listener.Name);
            if (traceDiagnostic != null)
            {
                //适配订阅
                listener.SubscribeWithAdapter(traceDiagnostic);
            }
        }
    }
}

using skywalking_test.zipkin;
using System.Diagnostics;
using zipkin4net.Annotation;
using zipkin4net.Middleware;
using zipkin4net.Tracers.Zipkin;
using zipkin4net.Transport.Http;
using zipkin4net;
using Microsoft.Extensions.Configuration;

namespace skywalking_test.zipkin
{
    public class ZipkinOptions
    {
        /// <summary>
        /// 服务名,可自定义
        /// </summary>
        public string ServiceName { get; set; }
        /// <summary>
        /// 服务地址
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        /// 记录数据密度,1.0代表全部记录,采样率的值介于 0 和 1 之间,表示需要保留的比例。例如,设置 TraceManager.SamplingRate 为 0.5 表示只有一半的请求会被记录下来进行分析
        /// </summary>
        public float SamplingRate { get; set; }
    }

    public static class ZipkinExtensions
    {
        public static IServiceCollection AddZipkin(this IServiceCollection services)
        {
            services.AddSingleton<ITraceDiagnosticListener, HttpDiagnosticListener>();
            return services.AddSingleton<TraceObserver>();
        }

        public static IApplicationBuilder UseZipkin(this IApplicationBuilder app, IHostApplicationLifetime lifetime)
        {
            var configuration = app.ApplicationServices.GetRequiredService<IConfiguration>();
            var zipkinOptions = new ZipkinOptions();
            configuration.GetSection("Zipkin").Bind(zipkinOptions);
            return UseZipkin(app, lifetime, zipkinOptions.ServiceName, zipkinOptions.Url, zipkinOptions.SamplingRate);
        }

        public static IApplicationBuilder UseZipkin(this IApplicationBuilder app, IHostApplicationLifetime lifetime, string serviceName, string zipkinUrl, float samplingRate = 1)
        {
            ILoggerFactory loggerFactory = app.ApplicationServices.GetRequiredService<ILoggerFactory>();
            var traceObserver = app.ApplicationServices.GetService<TraceObserver>();
            if (traceObserver != null)
            {
                DiagnosticListener.AllListeners.Subscribe(traceObserver);
            }
            lifetime.ApplicationStarted.Register(() =>
            {
                TraceManager.SamplingRate = samplingRate; //记录数据密度,1.0代表全部记录,采样率的值介于 0 和 1 之间,表示需要保留的比例。例如,设置 TraceManager.SamplingRate 为 0.5 表示只有一半的请求会被记录下来进行分析
                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;
        }
    }
}

3、配置文件添加配置:

"Zipkin": {
    "ServiceName": "testProj1",//在zipkin展示项目名称,可自定义
    "Url": "http://192.168.17.82:9411",
    "SamplingRate": 0.5
  }

4、在项目的Program.cs中添加配置:
//zipkin配置
builder.Services.AddZipkin();
app.UseZipkin(app.Lifetime);

5、完成,启动项目并请求接口进行测试,会在zipkin展示请求信息。

 


6、根据服务器承载量,如果需要调整采样率和数据过期时间,如下设置:
6.1 客户端项目里修改appsettings.json,修改”SamplingRate”,
记录数据密度,1.0代表全部记录,采样率的值介于 0 和 1 之间,表示需要保留的比例。例如,设置 TraceManager.SamplingRate 为 0.5 表示只有一半的请求会被记录下来进行分析。

6.2 服务端启动时可以添加–ES_MAX_SPAN_AGE=7d 修改数据过期时间

 
posted @ 2024-10-29 11:36  羊脂玉净瓶  阅读(21)  评论(0)    收藏  举报