微服务的追踪怎么实现?有哪些开源组件可以用?
在微服务架构中,分布式追踪(Distributed Tracing) 是一个关键的工具,用于监控和调试复杂的服务调用链。分布式追踪能够帮助开发者理解请求在各个服务之间的流动路径,识别性能瓶颈和故障点,从而提高系统的可靠性和性能。以下是实现微服务追踪的方法以及一些常用的开源组件。
实现分布式追踪的方法
- 上下文传播:
- 在服务之间的请求中传播追踪上下文信息,如追踪ID、跨度ID、采样决策等。
- 常用的上下文传播协议包括B3、W3C TraceContext等。
- 追踪数据收集:
- 收集每个服务中的追踪数据,如请求开始时间、结束时间、调用的服务、调用的资源等。
- 使用追踪库或框架来自动收集这些数据。
- 数据存储:
- 将追踪数据存储到集中式的存储系统中,如时序数据库、消息队列等。
- 常用的存储系统包括Elasticsearch、InfluxDB、Cassandra等。
- 数据可视化:
- 使用可视化工具来展示追踪数据,帮助开发者分析请求路径和性能问题。
- 常用的可视化工具包括Jaeger、Zipkin、Prometheus + Grafana等。
常用的开源组件
- Jaeger
-
特点:
- 由Uber开发的开源分布式追踪系统。
- 支持多种语言和框架。
- 提供强大的可视化界面。
- 支持B3、W3C TraceContext等上下文传播协议。
-
组件:
- Jaeger Agent:用于收集追踪数据。
- Jaeger Collector:用于接收并存储追踪数据。
- Jaeger Query:用于查询和展示追踪数据。
- Jaeger UI:提供可视化界面。
-
集成示例:
在.NET应用中使用Jaeger,可以通过Jaeger.Client库来实现。using Jaeger;
using Jaeger.Samplers;
using Jaeger.Reporters;
using Jaeger.Senders.Thrift.Http;
using OpenTracing;
using OpenTracing.Util;public class TracingConfig
{
public static ITracer InitTracer(string serviceName)
{
var sampler = new ConstSampler(true);
var reporter = new RemoteReporter.Builder()
.WithSender(new HttpSender("http://localhost:14268/api/traces", new Configuration.HttpSenderConfiguration(), new List()))
.Build();var tracer = new Tracer.Builder(serviceName)
.WithSampler(sampler)
.WithReporter(reporter)
.Build();GlobalTracer.Register(tracer);
return tracer;
}
}public class OrderService
{
private readonly ITracer _tracer;public OrderService(ITracer tracer)
{
_tracer = tracer;
}public void CreateOrder(OrderCreationDto orderDto)
{
using (var scope = _tracer.BuildSpan("CreateOrder").StartActive())
{
var span = scope.Span;
span.Log("Creating order");// 应用层逻辑:数据验证
if (orderDto.Items == null || orderDto.Items.Count == 0)
{
throw new ArgumentException("Order items are required.");
}// 创建订单本地事务
var order = new Order
{
UserId = orderDto.UserId,
Items = orderDto.Items.Select(itemDto => new OrderItem
{
ProductId = itemDto.ProductId,
Quantity = itemDto.Quantity
}).ToList(),
TotalAmount = orderDto.Items.Sum(itemDto => itemDto.Price * itemDto.Quantity)
};// 记录其他操作
span.Log("Order created");// 调用其他服务
var paymentService = new PaymentService(_tracer);
paymentService.ProcessPayment(order.Id, order.TotalAmount);
}
}
}
- Zipkin
-
特点:
- 由Twitter开发的开源分布式追踪系统。
- 支持多种语言和框架。
- 提供强大的可视化界面。
- 支持B3、W3C TraceContext等上下文传播协议。
-
组件:
- Zipkin Collector:用于接收并存储追踪数据。
- Zipkin Storage:支持多种存储后端,如Elasticsearch、Cassandra等。
- Zipkin Query:用于查询和展示追踪数据。
- Zipkin UI:提供可视化界面。
-
集成示例:
在.NET应用中使用Zipkin,可以通过Zipkin.Tracing库来实现。using Zipkin.Tracing;
using Zipkin.Tracing.Builder;
using Zipkin.Tracing.Core;
using Zipkin.Tracing.Handlers;
using Zipkin.Tracing.Http;
using OpenTracing.Util;public class TracingConfig
{
public static ITracer InitTracer(string serviceName)
{
var tracer = new TracerBuilder("my-service")
.WithSampler(new AlwaysSampler())
.WithReporter(new HttpReporter("http://localhost:9411/api/v2/spans"))
.Build();GlobalTracer.Register(tracer);
return tracer;
}
}public class OrderService
{
private readonly ITracer _tracer;public OrderService(ITracer tracer)
{
_tracer = tracer;
}public void CreateOrder(OrderCreationDto orderDto)
{
using (var scope = _tracer.BuildSpan("CreateOrder").StartActive())
{
var span = scope.Span;
span.Log("Creating order");// 应用层逻辑:数据验证
if (orderDto.Items == null || orderDto.Items.Count == 0)
{
throw new ArgumentException("Order items are required.");
}// 创建订单本地事务
var order = new Order
{
UserId = orderDto.UserId,
Items = orderDto.Items.Select(itemDto => new OrderItem
{
ProductId = itemDto.ProductId,
Quantity = itemDto.Quantity
}).ToList(),
TotalAmount = orderDto.Items.Sum(itemDto => itemDto.Price * itemDto.Quantity)
};// 记录其他操作
span.Log("Order created");// 调用其他服务
var paymentService = new PaymentService(_tracer);
paymentService.ProcessPayment(order.Id, order.TotalAmount);
}
}
}
- OpenTelemetry
-
特点:
- 由CNCF(Cloud Native Computing Foundation)维护的开源项目。
- 提供统一的API和SDK来收集和导出追踪数据。
- 支持多种语言和框架。
- 可以与多种后端集成,如Jaeger、Zipkin、Prometheus等。
-
组件:
- SDKs:提供用于收集追踪数据的SDK。
- Exporters:支持多种后端,如Jaeger、Zipkin、Prometheus等。
- Collectors:用于接收和存储追踪数据。
- UI:通过其他工具(如Jaeger UI、Zipkin UI)进行可视化。
-
集成示例:
在.NET应用中使用OpenTelemetry,可以通过OpenTelemetry库来实现。using OpenTelemetry;
using OpenTelemetry.Trace;
using OpenTelemetry.Exporter.Jaeger;
using OpenTelemetry.Instrumentation.HttpClient;
using System.Net.Http;public class TracingConfig
{
public static TracerProvider InitTracer(string serviceName)
{
return Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName))
.AddHttpClientInstrumentation()
.AddSource(serviceName)
.AddJaegerExporter(o =>
{
o.AgentHost = "localhost";
o.AgentPort = 6831;
})
.Build();
}
}public class OrderService
{
private readonly TracerProvider _tracerProvider;
private readonly HttpClient _httpClient;public OrderService(TracerProvider tracerProvider, HttpClient httpClient)
{
_tracerProvider = tracerProvider;
_httpClient = httpClient;
}public void CreateOrder(OrderCreationDto orderDto)
{
using (var activity = Telemetry.ActivitySource.StartActivity("CreateOrder"))
{
activity?.AddTag("order.id", orderDto.UserId);
activity?.AddTag("order.items", string.Join(", ", orderDto.Items.Select(i => i.ProductId)));// 应用层逻辑:数据验证
if (orderDto.Items == null || orderDto.Items.Count == 0)
{
throw new ArgumentException("Order items are required.");
}// 创建订单本地事务
var order = new Order
{
UserId = orderDto.UserId,
Items = orderDto.Items.Select(itemDto => new OrderItem
{
ProductId = itemDto.ProductId,
Quantity = itemDto.Quantity
}).ToList(),
TotalAmount = orderDto.Items.Sum(itemDto => itemDto.Price * itemDto.Quantity)
};// 记录其他操作
activity?.AddEvent(new ActivityEvent("Order created"));// 调用其他服务
var paymentService = new PaymentService(_httpClient);
paymentService.ProcessPayment(order.Id, order.TotalAmount);
}
}
}public class PaymentService
{
private readonly HttpClient _httpClient;public PaymentService(HttpClient httpClient)
{
_httpClient = httpClient;
}public void ProcessPayment(long orderId, decimal amount)
{
using (var activity = Telemetry.ActivitySource.StartActivity("ProcessPayment"))
{
activity?.AddTag("orderId", orderId);
activity?.AddTag("amount", amount);// 处理支付逻辑
var response = _httpClient.PostAsync($"http://paymentservice/process/{orderId}", null).Result;
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException("Payment processing failed.");
}// 记录其他操作
activity?.AddEvent(new ActivityEvent("Payment processed"));
}
}
}public class Program
{
public static void Main(string[] args)
{
var tracerProvider = TracingConfig.InitTracer("order-service");
var httpClient = new HttpClient();var orderService = new OrderService(tracerProvider, httpClient);
var orderDto = new OrderCreationDto
{
UserId = 123,
Items = new List
{
new OrderItemDto { ProductId = 456, Quantity = 2, Price = 10.0m }
}
};orderService.CreateOrder(orderDto);
}
}
其他开源组件
- Prometheus + Grafana
- Prometheus:一个开源的监控系统,可以收集和存储时间序列数据。
- Grafana:一个开源的分析和监控平台,支持多种数据源,包括Prometheus。
- 特点:
- 主要用于监控指标数据,但也可以与追踪数据结合使用。
- 支持强大的查询和可视化功能。
- ELK Stack (Elasticsearch, Logstash, Kibana)
- Elasticsearch:一个分布式搜索和分析引擎。
- Logstash:一个开源的数据收集引擎。
- Kibana:一个开源的数据可视化工具。
- 特点:
- 提供强大的日志收集和可视化功能。
- 可以与追踪数据结合使用,提供全面的监控和调试支持。
- Spring Cloud Sleuth (Java)
-
- 由Spring Cloud提供的分布式追踪解决方案。
- 支持B3、W3C TraceContext等上下文传播协议。
- 可以与多种追踪后端集成,如Zipkin、Jaeger等。
集成示例:
- Steeltoe ( .NET)
-
特点:
- 由Pivotal提供的微服务工具集。
- 支持分布式追踪、服务发现、配置管理等。
- 可以与多种追踪后端集成,如Zipkin、Jaeger等。
-
集成示例:
实现步骤
- 配置追踪库:
- 选择合适的追踪库(如Jaeger、Zipkin、OpenTelemetry)并进行配置。
- 上下文传播:
- 确保在服务之间的请求中传播追踪上下文信息。
- 收集追踪数据:
- 使用追踪库自动收集服务中的追踪数据。
- 导出追踪数据:
- 将收集到的追踪数据导出到集中式的存储系统或追踪后端。
- 可视化和分析:
- 使用可视化工具(如Jaeger UI、Zipkin UI)来展示和分析追踪数据。
示例:使用OpenTelemetry进行追踪
以下是一个更详细的示例,展示如何在.NET应用中使用OpenTelemetry进行分布式追踪。
-
安装必要的NuGet包
dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.Jaeger
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.HttpClient -
配置OpenTelemetry
using OpenTelemetry;
using OpenTelemetry.Trace;
using OpenTelemetry.Exporter.Jaeger;
using OpenTelemetry.Instrumentation.AspNetCore;
using OpenTelemetry.Exporter.OpenTelemetryProtocol;
using OpenTelemetry.Instrumentation.HttpClient;
using Microsoft.Extensions.DependencyInjection;
public class TracingConfig
{
public static TracerProvider InitTracer(string serviceName)
{
return Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName))
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation()
.AddJaegerExporter(o =>
{
o.AgentHost = "localhost";
o.AgentPort = 6831;
})
.Build();
}
} -
在应用程序中启用追踪
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 初始化OpenTelemetry追踪
TracingConfig.InitTracer("order-service");services.AddControllers();
}public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
} -
在控制器中使用追踪
using Microsoft.AspNetCore.Mvc;
using OpenTelemetry.Context.Propagation;
using System.Net.Http;
using System.Threading.Tasks;[ApiController]
[Route("api/[controller]")]
public class OrderController : ControllerBase
{
private readonly ITracer _tracer;
private readonly HttpClient _httpClient;public OrderController(TracerProvider tracerProvider, HttpClient httpClient)
{
_tracer = tracerProvider.GetTracer("order-service");
_httpClient = httpClient;
}[HttpPost]
public IActionResult CreateOrder(OrderCreationDto orderDto)
{
using (var span = _tracer.BuildSpan("CreateOrder").StartActive())
{
span.Span.SetTag("order.id", orderDto.UserId);
span.Span.SetTag("order.items", string.Join(", ", orderDto.Items.Select(i => i.ProductId)));// 应用层逻辑:数据验证
if (orderDto.Items == null || orderDto.Items.Count == 0)
{
span.Span.SetTag("error", "Order items are required.");
return BadRequest("Order items are required.");
}// 创建订单本地事务
var order = new Order
{
UserId = orderDto.UserId,
Items = orderDto.Items.Select(itemDto => new OrderItem
{
ProductId = itemDto.ProductId,
Quantity = itemDto.Quantity
}).ToList(),
TotalAmount = orderDto.Items.Sum(itemDto => itemDto.Price * itemDto.Quantity)
};// 记录其他操作
span.Span.Log("Order created");// 调用其他服务
var paymentService = new PaymentService(_tracer, _httpClient);
paymentService.ProcessPayment(order.Id, order.TotalAmount);return Ok(order);
}
}
}public class PaymentService
{
private readonly ITracer _tracer;
private readonly HttpClient _httpClient;public PaymentService(ITracer tracer, HttpClient httpClient)
{
_tracer = tracer;
_httpClient = httpClient;
}public void ProcessPayment(long orderId, decimal amount)
{
using (var span = _tracer.BuildSpan("ProcessPayment").StartActive())
{
span.Span.SetTag("orderId", orderId);
span.Span.SetTag("amount", amount);// 处理支付逻辑
var response = _httpClient.PostAsync($"http://paymentservice/process/{orderId}", null).Result;
if (!response.IsSuccessStatusCode)
{
span.Span.SetTag("error", "Payment processing failed.");
throw new InvalidOperationException("Payment processing failed.");
}// 记录其他操作
span.Span.Log("Payment processed");
}
}
}
关键点
- 上下文传播:
- 确保在服务之间的请求中传播追踪上下文信息。
- 自动收集:
- 使用OpenTelemetry的Instrumentation自动收集追踪数据。
- 导出追踪数据:
- 使用Jaeger Exporter将追踪数据导出到Jaeger Collector。
- 可视化:
- 使用Jaeger UI来展示和分析追踪数据。
总结
-
分布式追踪:是一种监控和调试微服务中复杂请求调用链的技术。
-
主要组件:
- 追踪库:如Jaeger、Zipkin、OpenTelemetry等。
- 上下文传播:如B3、W3C TraceContext等。
- 数据存储:如Elasticsearch、Cassandra等。
- 可视化工具:如Jaeger UI、Zipkin UI等。
-
OpenTelemetry:
- 提供统一的API和SDK来收集和导出追踪数据。
- 支持多种语言和框架。
- 可以与多种后端集成。
-
其他组件:
- Jaeger:由Uber开发的开源分布式追踪系统。
- Zipkin:由Twitter开发的开源分布式追踪系统。
- Prometheus + Grafana:用于监控指标数据。
- ELK Stack:用于日志收集和可视化。
- Spring Cloud Sleuth:用于Java微服务的分布式追踪。
- Steeltoe:用于.NET微服务的分布式追踪。
通过使用这些开源组件和策略,可以有效地实现微服务的分布式追踪,从而提高系统的监控能力和调试效率。

浙公网安备 33010602011771号