微服务的追踪怎么实现?有哪些开源组件可以用?

在微服务架构中,分布式追踪(Distributed Tracing) 是一个关键的工具,用于监控和调试复杂的服务调用链。分布式追踪能够帮助开发者理解请求在各个服务之间的流动路径,识别性能瓶颈和故障点,从而提高系统的可靠性和性能。以下是实现微服务追踪的方法以及一些常用的开源组件。

实现分布式追踪的方法

  1. 上下文传播:
    • 在服务之间的请求中传播追踪上下文信息,如追踪ID、跨度ID、采样决策等。
    • 常用的上下文传播协议包括B3、W3C TraceContext等。
  2. 追踪数据收集:
    • 收集每个服务中的追踪数据,如请求开始时间、结束时间、调用的服务、调用的资源等。
    • 使用追踪库或框架来自动收集这些数据。
  3. 数据存储:
    • 将追踪数据存储到集中式的存储系统中,如时序数据库、消息队列等。
    • 常用的存储系统包括Elasticsearch、InfluxDB、Cassandra等。
  4. 数据可视化:
    • 使用可视化工具来展示追踪数据,帮助开发者分析请求路径和性能问题。
    • 常用的可视化工具包括Jaeger、Zipkin、Prometheus + Grafana等。

常用的开源组件

  1. 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);
    }
    }
    }

  1. 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);
    }
    }
    }

  1. 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);
    }
    }

其他开源组件

  1. Prometheus + Grafana
  • Prometheus:一个开源的监控系统,可以收集和存储时间序列数据。
  • Grafana:一个开源的分析和监控平台,支持多种数据源,包括Prometheus。
  • 特点:
    • 主要用于监控指标数据,但也可以与追踪数据结合使用。
    • 支持强大的查询和可视化功能。
  1. ELK Stack (Elasticsearch, Logstash, Kibana)
  • Elasticsearch:一个分布式搜索和分析引擎。
  • Logstash:一个开源的数据收集引擎。
  • Kibana:一个开源的数据可视化工具。
  • 特点:
    • 提供强大的日志收集和可视化功能。
    • 可以与追踪数据结合使用,提供全面的监控和调试支持。
  1. Spring Cloud Sleuth (Java)
    • 由Spring Cloud提供的分布式追踪解决方案。
    • 支持B3、W3C TraceContext等上下文传播协议。
    • 可以与多种追踪后端集成,如Zipkin、Jaeger等。

集成示例:


org.springframework.cloud
spring-cloud-sleuth-zipkin

  1. Steeltoe ( .NET)
  • 特点:

    • 由Pivotal提供的微服务工具集。
    • 支持分布式追踪、服务发现、配置管理等。
    • 可以与多种追踪后端集成,如Zipkin、Jaeger等。
  • 集成示例:

实现步骤

  1. 配置追踪库:
    • 选择合适的追踪库(如Jaeger、Zipkin、OpenTelemetry)并进行配置。
  2. 上下文传播:
    • 确保在服务之间的请求中传播追踪上下文信息。
  3. 收集追踪数据:
    • 使用追踪库自动收集服务中的追踪数据。
  4. 导出追踪数据:
    • 将收集到的追踪数据导出到集中式的存储系统或追踪后端。
  5. 可视化和分析:
    • 使用可视化工具(如Jaeger UI、Zipkin UI)来展示和分析追踪数据。

示例:使用OpenTelemetry进行追踪
以下是一个更详细的示例,展示如何在.NET应用中使用OpenTelemetry进行分布式追踪。

  1. 安装必要的NuGet包

    dotnet add package OpenTelemetry
    dotnet add package OpenTelemetry.Exporter.Jaeger
    dotnet add package OpenTelemetry.Instrumentation.AspNetCore
    dotnet add package OpenTelemetry.Instrumentation.HttpClient

  2. 配置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();
    }
    }

  3. 在应用程序中启用追踪

    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();
    });
    }
    }

  4. 在控制器中使用追踪

    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");
    }
    }
    }

关键点

  1. 上下文传播:
    • 确保在服务之间的请求中传播追踪上下文信息。
  2. 自动收集:
    • 使用OpenTelemetry的Instrumentation自动收集追踪数据。
  3. 导出追踪数据:
    • 使用Jaeger Exporter将追踪数据导出到Jaeger Collector。
  4. 可视化:
    • 使用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微服务的分布式追踪。

通过使用这些开源组件和策略,可以有效地实现微服务的分布式追踪,从而提高系统的监控能力和调试效率。

OpenTelemetry 官方文档
Jaeger 官方文档
Zipkin 官方文档
Steeltoe 官方文档

posted @ 2024-12-27 16:28  似梦亦非梦  阅读(316)  评论(0)    收藏  举报