ABP VNext + Elastic APM:微服务性能监控

ABP VNext + Elastic APM:微服务性能监控 🚀


📚目录

  • [ABP VNext + Elastic APM:微服务性能监控 🚀](#ABP VNext + Elastic APM:微服务性能监控 🚀)
    • [一、引言 ✨](#一、引言 ✨)
      • [架构全景图 🏗️](#架构全景图 🏗️)
    • [二、环境与依赖 📦](#二、环境与依赖 📦)
    • [三、APM 服务器与 Kibana 快速部署 🐳](#三、APM 服务器与 Kibana 快速部署 🐳)
      • [Docker 网络示意图](#Docker 网络示意图)
    • [四、在 ABP VNext 中集成 Elastic APM .NET Agent ⚙️](#四、在 ABP VNext 中集成 Elastic APM .NET Agent ⚙️)
      • [4.1 安装与注册](#4.1 安装与注册)
      • [4.2 ABP 模块中注册中间件与标签](#4.2 ABP 模块中注册中间件与标签)
      • [4.3 自动采集范围](#4.3 自动采集范围)
      • [4.4 URL 过滤 🚫](#4.4 URL 过滤 🚫)
    • [五、自定义打点与标签 🎯](#五、自定义打点与标签 🎯)
    • [六、日志关联 📝](#六、日志关联 📝)
      • [6.1 Serilog](#6.1 Serilog)
      • [6.2 Microsoft.Extensions.Logging / NLog](#6.2 Microsoft.Extensions.Logging / NLog)
    • [七、Kibana APM 仪表盘构建 📊](#七、Kibana APM 仪表盘构建 📊)
      • [7.1 创建仪表盘(Dashboard)](#7.1 创建仪表盘(Dashboard))
      • [7.2 Transaction 概览](#7.2 Transaction 概览)
        • [响应时间分布(95th/99th 百分位)](#响应时间分布(95th/99th 百分位))
        • 吞吐量(TPS)
      • [7.3 服务依赖图(Service Map)](#7.3 服务依赖图(Service Map))
      • [7.4 错误监控](#7.4 错误监控)
      • [7.5 原始 Trace 搜索](#7.5 原始 Trace 搜索)
      • [7.6 告警与通知](#7.6 告警与通知)
    • [八、性能影响与采样策略 ⚖️](#八、性能影响与采样策略 ⚖️)
      • [8.1 配置示例(`appsettings.json`)](#8.1 配置示例(appsettings.json))
      • [8.2 性能调优要点](#8.2 性能调优要点)
      • [8.3 微基准测试](#8.3 微基准测试)
    • [九、端到端演示示例 🎬](#九、端到端演示示例 🎬)
    • [参考文档 📖](#参考文档 📖)

一、引言 ✨

TL;DR

  • 🕵️ 使用 Elastic.Apm.NetCoreAll 自动采集 HTTP、数据库、外部调用与错误性能指标
  • ⚙️ 支持环境变量与 appsettings.json 双重配置,零侵入式集成到 ABP VNext 微服务
  • 🔗 在 ABP 模块生命周期中注册 APM 中间件,并注入租户与用户标签(SetLabel API)
  • 📊 日志框架(Serilog、NLog、Microsoft.Extensions.Logging)一键关联 TraceId/TransactionId
  • 🧪 完整示例覆盖 URL 过滤、自定义 Span、微基准测试与性能调优

背景与动机

在微服务架构下,跨服务调用链长、性能瓶颈定位困难。Elastic APM 提供从事务到 Span、从代码层到基础设施的一体化可观察方案,能帮助我们在 Kibana 中实时查看响应分布、调用拓扑与错误热点。结合 ABP VNext 的模块化与多租户能力,可快速搭建高性能、可复现的 APM 监控流水线。

架构全景图 🏗️

应用 服务集群 HTTP/gRPC + TLS HTTP/gRPC + TLS gRPC/TCP HTTP HTTP Elastic APM Agent OrderService-1 OrderService-2 APM Server Elasticsearch Kibana APM UI


二、环境与依赖 📦

  • 平台版本

    • .NET 7/8
    • ABP VNext 7.x
  • Elastic Stack

    • Elasticsearch ≥ 8.x
    • Kibana ≥ 8.x(内置 APM 应用)
    • APM Server ≥ 8.x
  • NuGet 包

    • Elastic.Apm.NetCoreAll ------ 包含 HTTP、EF Core、SqlClient、Redis 等默认自动打点功能

    • 可选:

      • Elastic.Apm.EntityFrameworkCore(EF Core 细粒度支持)
      • Elastic.Apm.SqlClient(针对 MySQL.Data 或其他 ADO.NET 驱动的拓展)
      • Elastic.Apm.SerilogEnricher(Serilog 日志追踪关联)
      • Elastic.Apm.Extensions.Logging(Microsoft.Extensions.Logging 关联)

三、APM 服务器与 Kibana 快速部署 🐳

yaml 复制代码
version: '3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.5.0
    environment:
      - discovery.type=single-node
    ports: ["9200:9200"]

  kibana:
    image: docker.elastic.co/kibana/kibana:8.5.0
    ports: ["5601:5601"]

  apm-server:
    image: docker.elastic.co/apm/apm-server:8.5.0
    depends_on: ["elasticsearch"]
    ports: ["8200:8200"]
    command: >
      apm-server -e
        -E output.elasticsearch.hosts=["elasticsearch:9200"]

执行 docker-compose up -d 后,访问 http://localhost:5601/app/apm 确认 APM 界面可用。

Docker 网络示意图

Docker Host Elasticsearch:9200 APM Server:8200 Kibana:5601


四、在 ABP VNext 中集成 Elastic APM .NET Agent ⚙️

4.1 安装与注册

bash 复制代码
dotnet add package Elastic.Apm.NetCoreAll
dotnet add package Elastic.Apm.SerilogEnricher
dotnet add package Elastic.Apm.Extensions.Logging
配置来源
  • 环境变量(优先级最高)

    bash 复制代码
    export ELASTIC_APM_SERVER_URLS=http://localhost:8200
    export ELASTIC_APM_SERVICE_NAME=OrderService
    export ELASTIC_APM_ENVIRONMENT=production
    export ELASTIC_APM_TRANSACTION_SAMPLE_RATE=1.0
  • appsettings.json

    jsonc 复制代码
    "ElasticApm": {
      "ServerUrls": "http://localhost:8200",
      "ServiceName": "OrderService",
      "Environment": "production",
      "TransactionSampleRate": 1.0
    }

    Program.cs 中使用:

    csharp 复制代码
    builder.Services.AddAllElasticApm(builder.Configuration);

4.2 ABP 模块中注册中间件与标签

csharp 复制代码
public class OrderWebModule : AbpModule
{
    public override void OnApplicationInitialization(ApplicationInitializationContext context)
    {
        var app = context.GetApplicationBuilder();

        // 1) 注入 APM 中间件
        app.UseElasticApm(context.GetConfiguration());

        // 2) 全局标签注入:租户 & 用户
        Agent.Tracer.Subscribe(new LabelSubscriber(span =>
        {
            var tenant = context.ServiceProvider.GetService<ICurrentTenant>()?.Id?.ToString();
            var user   = context.ServiceProvider.GetService<ICurrentUser>()?.Id?.ToString();
            if (span is Transaction txn)
            {
                txn.SetLabel("tenantId", tenant);
                txn.SetLabel("userId",   user);
            }
        }));

        // 3) ABP 默认管道
        app.UseAbpRequestLocalization();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseConfiguredEndpoints();
    }
}

💡 使用 SetLabelLabelSubscriber,保证线程安全与一致性。

4.3 自动采集范围

  • HTTP/gRPC:自动创建 Transaction;
  • SQL 调用 :跟踪 System.Data.SqlClient / Microsoft.Data.SqlClient(含 Dapper) ;
  • 其他 ADO.NET 驱动 :可引入 Elastic.Apm.SqlClient 或 Profiler 模式;
  • 外部 HTTPHttpClient 自动跟踪;
  • 未捕获异常:自动上报 Error。

4.4 URL 过滤 🚫

jsonc 复制代码
"ElasticApm": {
  "TransactionIgnoreUrls": "/health*,/metrics*"
}

五、自定义打点与标签 🎯

csharp 复制代码
using Elastic.Apm;
using Elastic.Apm.Api;

// 自定义事务
using var transaction = Agent.Tracer.StartTransaction("ProcessOrder", "order");

try
{
    // 业务逻辑
}
catch (Exception ex)
{
    // 捕获并上报异常
    Agent.Tracer.CurrentTransaction?.CaptureException(ex);
    throw;
}

// 自定义 Span
transaction.CaptureSpan("CallPaymentGateway", "external", () =>
{
    // 第三方支付调用
});

// 额外标签
transaction.SetLabel("orderType", "Express");

💡 仅在关键路径添加 Span,避免过度细分导致存储与性能压力。


六、日志关联 📝

6.1 Serilog

csharp 复制代码
using Serilog;
using Elastic.Apm.SerilogEnricher;

Log.Logger = new LoggerConfiguration()
  .Enrich.WithElasticApmCorrelationInfo()
  .WriteTo.Console(
    outputTemplate: "[{ElasticApmTraceId} {ElasticApmTransactionId}] {Message:lj}{NewLine}{Exception}"
  )
  .CreateLogger();

builder.Host.UseSerilog();

6.2 Microsoft.Extensions.Logging / NLog

csharp 复制代码
builder.Logging
    .AddConsole()
    .AddConfiguration(builder.Configuration.GetSection("Logging"))
    .AddElasticApm(builder.Configuration);

📑 日志中包含 TraceId/TransactionId,便于跨系统日志与调用链关联


七、Kibana APM 仪表盘构建 📊

7.1 创建仪表盘(Dashboard)

  1. 在 Kibana 左侧菜单中,依次点击 "Dashboard" → "Create dashboard"
  2. 点击 "Create new visualization" ,选择 "Lens" 作为可视化工具。

7.2 Transaction 概览

响应时间分布(95th/99th 百分位)
  1. 在 Lens 中选择 APM transaction duration 指标。
  2. transaction.duration.us 拖到纵轴,设置聚合方式为 Percentile ,并在右侧设置 Percentiles95,99
  3. 保存为 "响应时间分布(P95/P99)",添加到 Dashboard。
吞吐量(TPS)
  1. 在 Lens 中选择 APM transactions per minute(或用 count 并按分钟做 X 轴)。
  2. 拖拽 @timestamp 到横轴,聚合方式设为 Date histogram(interval: auto)
  3. 拖拽 transaction.id 计数到纵轴(Count)。
  4. 保存为 "每分钟吞吐量 (TPS)",添加到 Dashboard。

7.3 服务依赖图(Service Map)

  1. 在 Kibana 左侧菜单点击 "Observability" → "Service map"
  2. 选择目标服务(如 OrderService),即可看到上下游依赖拓扑。
  3. 可切换时间范围和环境过滤标签,查看不同环境下的调用链。

7.4 错误监控

Error rate
  1. 新建 Visualization,选择 Lens
  2. 拖拽 Error count(apm.error.count)到纵轴,横轴同样用 Date histogram。
  3. 再拖一个 Transaction count (apm.transaction.duration.count),使用 Formula 计算 errors / transactions
  4. 保存为 "错误率(Error rate)"
异常类型聚合
  1. 在 Lens 中,选择 apm.error.exception.type 作为分组字段(Break down by)。
  2. 纵轴用 Count of errors
  3. 保存为 "异常类型分布"

7.5 原始 Trace 搜索

  1. 点击左侧 "Observability" → "APM" → "Traces"
  2. 在上方搜索框输入标签或 transaction.id:<ID>,点击 Search
  3. 浏览单次调用链,查看各个 Span 的详细耗时和堆栈。

7.6 告警与通知

  1. 在 Kibana 菜单中选择 "Alerting" → "Create rule"
  2. 规则类型选择 "APM transaction duration threshold"
  3. 配置阈值(如平均响应时间 > 500 ms)、时间窗口和触发条件。
  4. 添加动作(Email、Slack、Webhook 等)并启用规则。
  5. 在 Dashboard 中可以直接用 "Add panel" 引入告警状态监控。


八、性能影响与采样策略 ⚖️

8.1 配置示例(appsettings.json

jsonc 复制代码
"ElasticApm": {
  "TransactionSampleRate": 0.2,
  "SpanStackTraceMinDuration": "10ms",
  "StackTraceLimit": 200,
  "CaptureBody": "errors",
  "SanitizeFieldNames": ["password"],
  "TransactionIgnoreUrls": "/health*,/metrics*"
}

8.2 性能调优要点

  • 🔽 降低采样率可显著提升吞吐与减少资源占用
  • 🔧 调整堆栈阈值可降低内存与 GC 压力

8.3 微基准测试

csharp 复制代码
[MemoryDiagnoser]
public class ApmSamplingBenchmark
{
    private readonly HttpClient _client = new();

    [Params(1.0, 0.5, 0.2)]
    public double SampleRate;

    [GlobalSetup]
    public void Setup()
    {
        Environment.SetEnvironmentVariable(
          "ELASTIC_APM_TRANSACTION_SAMPLE_RATE",
          SampleRate.ToString());
        // 重启应用后执行 Benchmark
    }

    [Benchmark]
    public async Task CallOrderApi() =>
        await _client.GetAsync("https://localhost:5001/api/orders");
}

CI 跑分,仅供参考

SampleRate 吞吐 (ops/s) 内存 (MB) 覆盖率 (%)
1.0 5200 155 100
0.5 6100 125 80
0.2 7300 98 40

九、端到端演示示例 🎬

HTTP/gRPC + TLS gRPC/TCP HTTP HTTP ABP 微服务 Elastic APM Agent APM Server Elasticsearch Kibana APM UI

  1. 🚀 启动微服务集群与 Elastic Stack
  2. 🔄 调用下单接口,触发数据库与外部 HTTP
  3. 📈 在 Kibana 查看事务、错误与调用链
  4. 🐌 模拟慢查询与异常,验证告警与过滤规则

参考文档 📖

是的,为了让读者快速上手,建议把第七节的各小项都补充成"如何在 Kibana 中操作"------下面是一个示例补全:


相关推荐
shinelord明1 小时前
【计算机网络架构】网状型架构简介
大数据·分布式·计算机网络·架构·计算机科学与技术
GEM的左耳返1 小时前
Java面试实战:从基础到架构的全方位技术交锋
spring boot·微服务·云原生·java面试·技术解析·ai集成
tangzzzfan1 小时前
深入 Moya:从架构设计到现代 iOS App 网络层最佳实践
架构
创码小奇客1 小时前
Talos 使用全攻略:从基础到高阶,常见问题一网打尽
java·后端·架构
java叶新东老师3 小时前
k8s pod生命周期、初始化容器、钩子函数、容器探测、重启策略
云原生·容器·kubernetes
超级小忍4 小时前
Spring Cloud Gateway:微服务架构下的 API 网关详解
微服务·云原生·架构
要开心吖ZSH4 小时前
【Spring Cloud Gateway 实战系列】高级篇:服务网格集成、安全增强与全链路压测
spring cloud·微服务·gateway·istio
GEM的左耳返4 小时前
Java面试新趋势:云原生与新兴框架实战解析
云原生·graalvm·服务网格·java面试·quarkus·micronaut
用户7785371836964 小时前
跨平台自动化框架的OCR点击操作实现详解与思考
架构
tangzzzfan4 小时前
Swinject 在 iOS 开发(MVVMC 架构)中的核心作用
架构