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 修改数据过期时间

浙公网安备 33010602011771号