Skip to content

搜索与日志技术栈视野 ​

S8-008选修高级约 60 分钟JDK 21持续学习 · 技术资产与输出

1. 本节定位 ​

日志与搜索是「可观测」与「检索」两条线的交汇处 —— 而它们的选型原则只有一条:先定查询需求,再选存储 ✓✓。

★ 本节用工具扫了本仓库的真实代码(数据不是编的) ✓✓:

text
现状扫描(labs 的 Java 代码):
  Java 文件 238 个
  System.out.println:3968 处
  结构化日志(log.info 等):11 处,分布在 4 个文件
★ 教学实验用 stdout 是**刻意的**(输出可复现);生产必须反过来:
  **结构化日志 + 集中采集**(12-Factor 之 XI)✓✓✓

★ 工具:python -X utf8 scripts/growth/log_stack.py ✓

2. 学习目标 ​

  • 能按「查询需求」选择日志/搜索技术栈 ★★★;
  • 掌握日志的落地三原则(stdout / trace_id / 结构化)★★★;
  • 知道 ELK / Loki / ClickHouse 的取舍 ★★★;
  • 会设计「出事时要问的五个问题」——反过来决定日志字段 ★★★。

3. 前置知识检查 ​

4. 为什么需要这个知识 ​

★ 日志的两种命运 ✗✓:

命运原因
出事时救命 ✓✓✓字段设计合理、集中采集、可按 trace_id 串起来
出事时没用 ✗✗日志在容器里、非结构化、没有上下文 ID

★★ 判断标准 ✓✓:「出事时能不能最快回答一个具体问题」 —— 设计日志格式时,先写下你未来要问的五个问题 ✓✓✓。

5. 核心概念 ​

5.1 三条落地原则(实测对照)★★★ ​

原则反例(常见)✗正例 ✓
应用只写 stdout自己写文件 + 轮转(容器销毁即丢失)✗✗单行 JSON → 平台采集 ✓✓
必须有 trace_id一堆无关联的日志行 ✗trace_id 串起链路(与 T2-016 配套)✓✓✓
结构化字段log.info("用户下单成功:" + json) ✗orderId / userId / costMs 独立字段 ✓✓

★ 实测数据(本仓库) ✓✓:3968 处 System.out.println vs 11 处结构化日志 —— 这正是「教学代码」与「生产代码」的分野: 教学要可复现的输出,生产要可检索的字段 ✓✓✓。

5.2 选型对照(按查询需求)★★★ ​

层次代表组件选型要点
采集Filebeat / Fluent Bit / Vector容器侧读 stdout 并转发 ✓
存储与检索Elasticsearch / OpenSearch全文检索强、生态成熟;成本较高 ✓
轻量聚合Loki + Grafana只索引标签、不索引全文;成本低 ✓✓
结构化分析ClickHouse高吞吐写入 + SQL 聚合;适合长周期报表 ✓✓
应用内检索Lucene / ES 客户端站内搜索、商品检索 ✓
链路追踪OpenTelemetry + Jaeger / Tempotrace_id 串联日志与指标 ✓✓✓

★★ 判据(照做即可) ✓✓✓:

text
要「全文检索」(按内容搜)      → Elasticsearch / OpenSearch ✓
只要「按标签查」(service=order, level=error) → Loki(成本低一个量级)✓✓
要「长周期聚合统计」(每天错误率曲线)→ ClickHouse ✓✓

5.3 「五个问题」法:反向设计日志字段 ★★★ ​

text
示例(订单服务):
① 这个订单为什么失败?        → orderId 必带 ✓
② 慢在哪一步?                → step + costMs 字段 ✓
③ 是哪次请求、谁调的?        → trace_id + userId + 来源 IP ✓
④ 失败率是多少(按小时)?    → level + 结构化时间戳(便于聚合)✓
⑤ 是不是版本发布引入的?      → version/gitSha 字段 ✓✓✓

★ 五个问题写完,日志字段清单就有了 —— **这比"抄一个日志模板"有效得多** ✓✓✓

5.4 与可观测三支柱的关系 ★★ ​

text
指标(Metrics):聚合、低成本、看趋势 → 「什么时候开始坏的?」✓
日志(Logs)   :明细、高成本、看细节 → 「具体是哪一条坏?为什么?」✓✓
追踪(Traces) :链路、看拓扑、看耗时 → 「坏在哪一跳?」✓✓✓
★ 三者用 trace_id 串起来才有合力(只有其一都是半盲)✓✓✓

6. 递进示例 ​

6.1 从「一行日志」到「可检索」 ​

text
✗ System.out.println("下单失败 " + e.getMessage());
✓ log.warn("order create failed: orderId={} userId={} step={} costMs={} err={}",
            orderId, userId, step, cost, e.getMessage());
★ 结构化字段 = 可聚合、可告警、可回溯 ✓✓✓

6.2 采集链路(最小闭环) ​

text
应用 stdout(单行 JSON)
  → 采集器(Filebeat / Fluent Bit)打标签(service / env / version)
  → 存储(Loki 或 ES)→ 查询面板(Grafana / Kibana)→ 告警规则 ✓✓

6.3 反例:把日志级别当装饰 ​

text
全部打成 INFO(或全部 ERROR)✗✗ → 告警噪声、成本爆炸
正解:**ERROR = 需要人行动**;WARN = 需要关注;INFO = 关键业务节点 ✓✓✓

7. 完整可运行工具与实测 ​

工具:scripts/growth/log_stack.py

运行:

powershell
python -X utf8 scripts/growth/log_stack.py

实测输出(节选):

text
===== 1. 现状扫描:labs 的 Java 代码在怎么输出?=====
  Java 文件 238 个
  System.out.println:3968 处
  结构化日志(log.info 等):11 处,分布在 4 个文件
===== 3. 三条落地建议 =====
  · **应用只写 stdout**(结构化单行 JSON):轮转、保留、采集都是平台的事 ✓✓✓
  · **日志里必须有 trace_id**:否则链路追踪与日志是两张皮 ✓✓
  · **先定查询需求再选存储**:要全文检索 → ES/OpenSearch;只要按标签查 → Loki ✓✓

8. Debug 观察点 ​

  1. 统计你负责服务的「日志级别分布」:ERROR 是不是太多/太少?✓✓;
  2. 抽一条线上问题,看你能否只靠现有日志回答那五个问题 ✓✓✓;
  3. 算一笔成本账:每天日志量 × 保留天数(决定 ES 还是 Loki)✓✓;
  4. 检查日志里有没有敏感信息(手机号/身份证/密码)✗✗✓。

9. 常见错误 ​

#错误说明
1日志写本地文件 ✗✗✗容器里 = 事后全丢 ✓✓
2非结构化(拼接字符串) ✗✗无法聚合与告警 ✓✓
3没有 trace_id ✗✗排查时无法串联 ✓
4级别滥用(全 INFO) ✗✗成本高、告警噪声 ✓
5把敏感信息写进日志 ✗✗✗合规事故 ✓✓
6先买存储再想查询需求 ✗选型必须从问题出发 ✓✓

10. 动手实验 ​

  1. 跑 log_stack.py,读现状扫描与选型表 ✓✓;
  2. 为你的服务写下「五个问题」并输出日志字段清单 ✓✓✓;
  3. 把一处 System.out.println 改成结构化日志,验证能被采集与查询 ✓✓;
  4. 用 Loki 或 ES 搭一个最小链路(本地 Docker 亦可),跑通「写入 → 查询 → 告警」✓✓✓。

验收方式:给一份服务的日志规范(字段 / 级别 / 采集链路 / 保留策略),且能回答那五个问题。

扩展任务:把本知识库 labs 的日志用法整理成《教学代码 vs 生产代码的日志差异》短文(《技术写作与博客》 的写作流程)✓✓

11. 练习题 ​

  1. 日志的三条落地原则?
  2. ES/OpenSearch 与 Loki 的判据是什么?
  3. 「五个问题法」怎么用来设计字段?举两个字段例子。
  4. 可观测三支柱各自回答什么问题?如何串联?
  5. ERROR 级别应该怎么用?
参考答案(要点)
  1. stdout / trace_id / 结构化 ✓✓★
  2. 要全文检索 → ES/OpenSearch;只按标签查 → Loki(成本低) ✓✓★
  3. 先写问题,再定字段(如 orderId、step+costMs、version/gitSha)✓✓★
  4. 指标看趋势、日志看细节、追踪看链路;用 trace_id 串联 ✓✓★
  5. ERROR = 需要人行动;否则降级并清理噪声 ✓✓★

12. 掌握标准 ​

  • [ ] 会按查询需求选型 ★★★;
  • [ ] 会写「五个问题」并产出字段清单 ★★★;
  • [ ] 掌握日志三原则与级别规范 ★★★;
  • [ ] 知道三支柱怎么串联 ★★★。

13. 扩展资源 ​

14. 下一步学习 ​

S8 持续学习到此收官(《Spring 源码阅读方法》~《开源项目阅读方法》 源码与开源阅读 → 《技术写作与博客》 写作 → 《架构案例与解决方案沉淀》 沉淀 → 《团队分享与知识输出》 分享 → 《前沿方向:云原生与 AI 应用开发》 前沿 → 本节 日志与搜索)。 整条学习路线到此完成:从 S0 环境到 S8 持续学习,214 个知识点全部有课程。 下一步:用这套知识库做一次完整的求职闭环(《目标岗位 JD 分析与能力差距清单》 → 《内部转岗沟通与材料》),并把每轮的复盘回填进本知识库 ✓✓✓

后续知识

暂无

进度只保存在本机浏览器,可随时清除

个人学习项目:AI 生成内容均经人工复核,第三方资源仅作索引