ELK 日志系统与 SkyWalking 监控 项目仓库java-concurrency-security:用于学习使用的的项目。基于 Spring Boot 2.7 的高并发性能调优 安全监控完整脚手架涵盖 JVM 调优、线程池优化、Redis 缓存防护、分库分表、OAuth2.0 认证、API 网关、ELK 日志收集、SkyWalking APM 监控等核心能力。 - AtomGit | GitCode前言为什么要做日志和监控类比想象你经营一家连锁餐厅。日志系统 每个店里的点单记录本记录每一单的情况。客户投诉菜不好吃翻记录。APM 监控 实时监控摄像头 业务分析仪表板。哪个菜做得最慢哪个时段最忙没有日志和监控 餐厅老板在黑灯瞎火中经营出问题全靠猜。1. ELK 日志收集系统1.1 什么是 ELK类比ELK 就像餐厅的中央监控中心 智能检索系统。组件角色类比Elasticsearch存储和搜索监控中心的硬盘存所有录像Logstash数据处理监控中心的图像识别机把模糊画面变清晰Kibana可视化监控中心的大屏幕显示器让老板看明白Filebeat数据采集每个分店装的摄像头采集数据1.2 架构总览数据流就像快递包裹应用日志→ 快递员收件Filebeat→ 仓库分拣Logstash→ 仓库存储ES→ 客户取件看明细Kibana1.3 Elasticsearch 索引设计类比ES 的索引就像图书馆的分类。 索引设计不好 图书馆没分类找书要花一年。索引模板PUT _template/app-log { index_patterns: [app-log-*], template: { settings: { number_of_shards: 3, // 分成 3 个分片库 number_of_replicas: 1, // 每个分片 1 副本备份 refresh_interval: 5s // 每 5 秒刷新一次 }, mappings: { properties: { timestamp: { type: date }, level: { type: keyword }, // 精确匹配不要分词 service: { type: keyword }, traceId: { type: keyword }, message: { type: text, // 全文检索 fields: { raw: { type: keyword } } // 也支持精确匹配 }, class: { type: keyword }, host: { type: keyword } } } } }textvskeyword的区别text会分词适合全文搜索。比如搜索异常能匹配发生异常了keyword不分词适合精确匹配。比如level: ERROR索引生命周期ILM类比就像食品的有效期管理。阶段时间操作类比Hot0~1天写入 查询rollover 30GB/天新鲜食品放冷柜Warm1~7天只读shrink 合并分片临期食品放普通货架Cold7~30天冻结减少资源占用临过期食品单独仓库Delete 30天自动删除过期扔掉为什么要分阶段1 个月内的日志经常要查Hot/Warm 1 个月以上的很少查Cold不查的直接删。 全部用热存储太贵了ES 集群要扩容。1.4 Logstash 数据处理管道类比Logstash 就像快递分拣中心做 3 件事拆包裹解析、贴标签增强、转发到对应分拣区输出。input { beats { port 5044 # 接收 Filebeat 推送的日志 } } filter { # 1. 拆包裹解析 JSON 格式 json { source message } # 2. 贴标签识别错误日志 if [level] ERROR { mutate { add_tag [error_log] } } # 3. 解析非结构化文本Java 异常堆栈 grok { match { message %{TIMESTAMP_ISO8601:log_timestamp} \[%{DATA:thread}\] %{LOGLEVEL:level} %{JAVACLASS:class} - %{GREEDYDATA:log_message} } } } output { elasticsearch { hosts [http://elasticsearch:9200] index app-log-%{YYYY.MM.dd} # 按天建索引 } }Grok 是什么一组预定义的日志模板可以自动提取日志中的字段。 比如把2024-01-15 10:23:45 [main] ERROR UserService - 用户不存在自动解析成{timestamp: 2024-01-15 10:23:45, thread: main, level: ERROR, class: UserService, message: 用户不存在}1.5 Filebeat 日志采集类比Filebeat 是轻量级的巡逻员每台服务器上装一个负责把日志推到 Logstash。关键配置filebeat.inputs: - type: log paths: - /var/log/app/*.log # 要采集的日志文件 fields: service: my-app # 给日志打标签 env: production # Java 异常堆栈是多行的必须合并 multiline: pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2} # 以日期开头的行是新日志 negate: true match: after # 不匹配新开头的行并到上一条多行合并举例2024-01-15 ERROR UserService - 用户不存在 at UserService.getUser(UserService.java:25) ← 异常堆栈 at UserController.query(UserController.java:42) ← 异常堆栈不合并的话会被当成 3 条独立的日志查询时只能看到用户不存在看不到堆栈。1.6 Kibana 可视化推荐 Dashboard 面板面板类型用途类比错误率趋势Line Chart按时间展示 ERROR 日志数量餐厅今天出了几次错QPS 统计Line Chart请求量趋势餐厅每天接待多少客人P99 延迟Area Chart99% 的请求响应时间99% 的客人等了多久Top10 慢接口Table按平均耗时排序哪道菜做菜最慢服务健康度Metric各服务成功率各分店评分日志搜索Discover按 traceId 关联查询按订单号找完整记录常用查询语法KQL# 搜索所有 ERROR 日志 level: ERROR # 搜索特定服务 service: order-service # 搜索特定 traceId全链路追踪的身份证 traceId: abc123def456 # 搜索时间范围最近 1 小时 timestamp: [now-1h TO now] # 组合查询order-service 的 timeout 错误 level: ERROR AND service: order-service AND message: timeoutP99 延迟是什么100 个请求中最慢的那个就是 P99。 95% 的请求 200ms 内完成剩下 5% 慢一点 平均延迟 250ms。 但 P99 可能是 2000ms个别请求极慢这种长尾问题很值得关注。2. SkyWalking APM 监控2.1 什么是 APM类比APMApplication Performance Management就像餐厅的实时运营仪表板。ELK 看的是日志明细类似点单记录APM 看的是性能指标类似实时营业数据工具关注点类比ELK错误排查出了什么事客户投诉记录APM性能分析哪里慢、哪里卡营业数据大盘告警主动通知出问题了立刻叫火灾报警器2.2 架构总览各组件职责组件角色类比Java Agent嵌在应用里自动采集调用链安装在每个分店的记账员OAP Server接收、聚合、分析数据数据中心Elasticsearch存储数据库SkyWalking UI图形化展示老板看的总控大屏2.3 Java Agent 接入零代码侵入不用改一行代码只在启动时加个 -javaagent 参数。java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \ -Dskywalking.agent.service_nameorder-service \ -Dskywalking.collector.backend_serviceoap-server:11800 \ -jar order-service.jar自动采集的能力不用写代码采集项用途HTTP 请求Spring MVC看到每个 API 调用的耗时数据库调用JDBC/MyBatis看到每条 SQL 的耗时Redis 调用看到缓存命中/未命中MQ 消息Kafka/RabbitMQ看到消息生产消费耗时线程池异步看到异步任务的执行情况2.4 核心概念看 SkyWalking UI 必备类比一家餐厅客户点了一道菜从下单到上桌的过程可以这样描述概念说明类比Trace一次完整请求的全链路调用客户点菜 → 后厨做菜 → 传菜员上菜 的全过程Segment单个服务内的处理跨度后厨 这一段Span最小执行单元切菜 1 分钟、炒菜 2 分钟、摆盘 30 秒Endpoint服务暴露的接口菜单上的菜名如/api/order/createService微服务实例一个分店实际例子2.5 自定义埋点特殊业务场景大部分场景自动埋点就够了。但有些业务逻辑比如复杂的计算、外部 API 调用需要手动标记。RestController public class OrderController { Trace(check-stock) // 标记一个 SpanUI 上能看耗时 public void checkStock(Long productId) { // 获取 TraceId 写入日志和 ELK 联动 String traceId TraceContext.traceId(); MDC.put(traceId, traceId); // 业务逻辑... } }2.6 告警规则配置出问题立刻叫类比餐厅里的自动报警器。配置文件config/skywalking/alarm-settings.yml规则阈值类比通俗理解服务响应时间 1000ms客人等 1 分钟还没上菜平均响应慢服务成功率 80%10 道菜 2 道做错错误率太高实例响应时间 2000ms某分店特别慢某节点问题端点响应时间 1500ms某道菜特别慢某个接口问题数据库响应 500ms仓库取货特别慢数据库瓶颈告警触发机制比如服务响应时间 1000ms的规则 - 时间窗口10 分钟 - 触发条件在这 10 分钟内至少有 3 次超过 1000ms - 静默期5 分钟避免重复打扰 → 满足条件后SkyWalking 通过 Webhook 推送到钉钉/企微2.7 Webhook 告警webhooks: - http://alert-handler:8080/webhook # 推送到告警处理服务告警回调数据示例{ scopeId: 1, name: order-service, id0: 12, ruleName: service_resp_time_rule, alarmMessage: 服务 order-service 响应时间超过 1秒, startTime: 1620000000000 }对接钉钉/企微你需要一个告警处理服务接收 Webhook 然后转发到钉钉机器人/企微 Webhook。最终效果群里自动弹出order-service 慢了 1 秒。2.8 SkyWalking 与 ELK 联动最强组合类比餐厅监控室和点单本配合使用。完整工作流实现方式日志里输出 traceId# logback 配置 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n占位符说明占位符含义示例输出%d{...}时间戳2026-07-10 14:30:25.123%thread线程名http-nio-8080-exec-1%X{traceId}链路追踪 IDabc-123-def-456%-5level日志级别左对齐5位INFO、ERROR%logger{36}类名缩写c.w.o.service.OrderService%msg日志消息内容订单查询成功%n换行符—SkyWalking 会自动把 traceId 放到 MDC线程上下文所以日志里能输出。3. Docker Compose 一键部署一句话拉起所有基础设施docker-compose up -d服务端口速查服务端口用途MySQL ds03306分库 0MySQL ds13307分库 1Redis6379缓存Elasticsearch9200日志/链路存储Kibana5601日志可视化Logstash5044日志处理SkyWalking OAP11800 / 12800APM 分析引擎SkyWalking UI8888APM 可视化面板4. 监控指标体系一张表看懂类比给餐厅装全方位监控摄像头覆盖各个层级。层级关注指标工具类比应用层QPS、响应时间、错误率SkyWalking监控上菜速度和做菜错误率中间件层Redis 命中率、连接池使用率Actuator Prometheus监控调料柜的使用情况数据库层慢查询、连接数、QPSMySQL Exporter监控仓库的进出货效率系统层CPU、内存、磁盘 IONode Exporter监控厨房设备运行状况日志层ERROR 数量、日志延迟ELK监控点单记录和异常记录黄金原则监控要分层应用/中间件/数据库/系统告警要分级P0 立即处理 / P1 1小时内处理 / P2 日常优化告警要可执行不能光发服务出错了要说明哪个服务 哪个接口 怎么修