霸王餐API项目实战:Java后端基于ELK的接口日志分析与监控搭建

在高并发的“霸王餐”营销系统中,接口调用链路复杂、第三方依赖多,传统日志文件难以满足实时追踪、异常告警和性能分析需求。本文以 baodanbao.com.cn 项目为例,展示如何通过 Logback + Logstash + Elasticsearch + Kibana(ELK)栈实现结构化日志采集、关键字段提取与可视化监控。

1. 引入依赖与配置Logback输出JSON格式

首先在 pom.xml 中添加 Logstash Appender:

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.4</version>
</dependency>

配置 logback-spring.xml,将日志以 JSON 格式输出到 TCP 端口(供 Logstash 消费):

<configuration>
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>localhost:5000</destination>
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp/>
                <logLevel/>
                <loggerName/>
                <message/>
                <mdc/> <!-- 支持 MDC 字段注入 -->
                <arguments/>
                <stackTrace/>
            </providers>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="LOGSTASH"/>
    </root>
</configuration>

在这里插入图片描述

2. 在接口层注入关键业务字段到MDC

利用 SLF4J 的 MDC(Mapped Diagnostic Context)机制,在请求入口注入追踪ID、用户ID、平台等维度:

package baodanbao.com.cn.controller;

import org.slf4j.MDC;
import org.springframework.web.bind.annotation.*;
import baodanbao.com.cn.service.FreeMealService;

@RestController
public class FreeMealController {

    private final FreeMealService freeMealService;

    public FreeMealController(FreeMealService freeMealService) {
        this.freeMealService = freeMealService;
    }

    @PostMapping("/api/v1/free-meal/submit")
    public ResponseEntity<?> submitFreeMeal(@RequestBody SubmitRequest req) {
        // 注入关键上下文
        MDC.put("traceId", generateTraceId());
        MDC.put("userId", req.getUserId());
        MDC.put("platform", req.getPlatform());
        MDC.put("orderId", req.getOrderId());

        try {
            freeMealService.process(req);
            return ResponseEntity.ok().build();
        } finally {
            MDC.clear(); // 防止线程复用污染
        }
    }

    private String generateTraceId() {
        return java.util.UUID.randomUUID().toString().replace("-", "");
    }
}

3. 自定义日志记录器封装业务事件

在核心服务中记录结构化事件,便于后续聚合分析:

package baodanbao.com.cn.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class FreeMealService {

    private static final Logger log = LoggerFactory.getLogger(FreeMealService.class);

    public void process(SubmitRequest req) {
        log.info("霸王餐提交开始");

        // 调用第三方
        boolean success = callThirdParty(req);

        if (success) {
            log.info("返利创建成功", 
                kv("rebateAmount", req.getAmount()),
                kv("strategyType", req.getStrategy())
            );
        } else {
            log.warn("第三方调用失败",
                kv("errorCode", "THIRD_PARTY_TIMEOUT"),
                kv("platform", req.getPlatform())
            );
        }
    }

    // 辅助方法:生成键值对(兼容 Logstash 字段提取)
    private Object kv(String k, Object v) {
        return new Object[]{k, v};
    }

    private boolean callThirdParty(SubmitRequest req) {
        // 模拟调用
        return true;
    }
}

注:kv 方法配合 Logback 的 arguments provider,可使日志自动展开为独立字段。

4. Logstash配置解析与过滤

编写 logstash.conf,监听 5000 端口并解析 JSON 日志:

input {
  tcp {
    port => 5000
    codec => json_lines
  }
}

filter {
  # 提取 MDC 中的字段到顶层
  mutate {
    add_field => {
      "trace_id" => "%{[mdc][traceId]}"
      "user_id" => "%{[mdc][userId]}"
      "platform" => "%{[mdc][platform]}"
      "order_id" => "%{[mdc][orderId]}"
    }
  }

  # 移除原始 mdc 嵌套字段
  mutate {
    remove_field => ["mdc"]
  }

  # 时间戳处理
  date {
    match => ["timestamp", "ISO8601"]
    target => "@timestamp"
  }
}

output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "baodanbao-free-meal-%{+YYYY.MM.dd}"
  }
}

5. Elasticsearch索引模板优化查询性能

创建索引模板,显式定义字段类型,避免动态映射导致 keyword/text 混乱:

PUT _template/baodanbao_free_meal_template
{
  "index_patterns": ["baodanbao-free-meal-*"],
  "mappings": {
    "properties": {
      "trace_id": { "type": "keyword" },
      "user_id": { "type": "keyword" },
      "platform": { "type": "keyword" },
      "order_id": { "type": "keyword" },
      "rebateAmount": { "type": "float" },
      "level": { "type": "keyword" },
      "logger_name": { "type": "keyword" },
      "message": { "type": "text" }
    }
  }
}

6. Kibana构建核心监控看板

在 Kibana 中创建以下可视化组件:

  • 请求量趋势图:按 @timestamp 聚合 count(),筛选 logger_name: "baodanbao.com.cn.controller.FreeMealController"
  • 错误率仪表盘:计算 level: "WARN" OR level: "ERROR" 占总请求比例
  • 平台调用量排名:Terms 聚合 platform 字段
  • 慢接口追踪:结合 APM 或自定义耗时字段(可通过 MDC 记录 duration_ms

例如,在 Controller 中补充耗时:

long start = System.currentTimeMillis();
try {
    freeMealService.process(req);
} finally {
    MDC.put("duration_ms", String.valueOf(System.currentTimeMillis() - start));
    MDC.clear();
}

通过上述 ELK 链路,baodanbao.com.cn 的霸王餐接口实现了全链路可观测性,支持秒级异常发现、用户行为追踪与容量规划。

本文著作权归 俱美开放平台 ,转载请注明出处!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐