面试追问地图

主问题必讲关键点下一层追问
top/vmstatCPU、load、运行队列、上下文切换CPU 空闲但 load 高的原因
freeavailable、cache、swap容器内存和宿主机内存差异
iostatawait、util、队列高 util 是否一定代表磁盘瓶颈
ss/lsof监听、连接状态、进程CLOSE_WAIT/TIME_WAIT 排查
jstack/jmap/jstat线程、堆、GC在线导出堆的风险
Arthasthread、trace、watch高开销命令如何控制影响
Docker镜像层、容器、namespace/cgroup容器退出后数据、镜像优化
JVM 容器化Xmx、非堆、RSS、限制OOMKilled 与 Java OOM 区别
K8s 探针readiness/liveness/startup错误探针为何引发重启风暴
发布策略滚动、蓝绿、金丝雀数据库兼容、自动回滚指标
可观测性日志、指标、TraceTrace 采样、敏感信息、告警降噪

命令题不仅要说命令名,还要说明关键列、异常特征,以及看到结果后的下一步。


一、Linux 常用排查命令

常用系统资源命令有哪些?

命令主要用途
top / htopCPU、内存、负载、进程
vmstatCPU、内存、运行队列、上下文切换
free -h内存和 Swap
iostat -x磁盘吞吐、延迟和利用率
df -h / du -sh文件系统和目录占用
ss -lntp监听端口和 TCP 连接
lsof文件、端口和进程关联
pidstat进程或线程级 CPU、IO、上下文切换

Linux load average 是什么?

Load Average 表示一段时间内:

  • 正在使用 CPU 的任务。
  • 等待 CPU 的可运行任务。
  • Linux 中不可中断睡眠的任务,常见于 IO 等待。

不能简单认为 load 大于 CPU 核数就一定有问题,还要结合 CPU 利用率、IO wait 和运行队列判断。

Buffers/Cache 占用高是否代表内存不足?

不一定。Linux 会利用空闲内存做文件缓存,并在应用需要时回收。

判断内存是否紧张主要看:

  • available 内存。
  • Swap 是否持续增长。
  • 是否频繁发生 major page fault。
  • 是否出现 OOM Killer。

服务端口不通怎么排查?

进程是否启动

端口是否监听、监听在哪个地址

本机 curl/telnet 是否成功

防火墙、安全组、容器端口映射

DNS、路由、负载均衡和上游代理

常用命令:

ss -lntp
curl -v http://127.0.0.1:8080/health
nslookup example.com
traceroute example.com

二、JVM 诊断工具

jpsjstackjmapjstat 分别做什么?

工具用途
jps查看 Java 进程
jstack导出线程栈,分析死锁和阻塞
jmap查看堆信息或导出堆快照
jstat查看 GC、堆各区域和类加载统计
jcmd向 JVM 发送诊断命令,能力较综合

线上使用导出堆等重操作前,要评估停顿时间、磁盘空间和敏感数据风险。

Arthas 常用能力?

  • dashboard:查看线程、内存和 GC 概况。
  • thread:定位高 CPU 线程和阻塞线程。
  • watch:观察方法入参、返回值和异常。
  • trace:分析方法调用耗时。
  • tt:记录并重放方法调用现场。
  • jad:反编译运行中的类。

诊断工具用于快速建立证据,不应长期在生产环境执行高开销命令。


三、Docker

镜像和容器的区别?

  • 镜像:只读模板,包含程序、依赖和运行环境。
  • 容器:镜像的运行实例,增加可写层和运行时状态。

镜像应保持可重复构建,容器应尽量无状态,持久数据放在外部存储或卷中。

Dockerfile 如何优化?

  • 使用合适且固定版本的基础镜像。
  • 使用多阶段构建,减少最终镜像体积。
  • 合并相关 RUN,清理包管理缓存。
  • 先复制依赖描述文件,充分利用构建缓存。
  • 使用非 root 用户运行。
  • 不把密钥和环境配置打进镜像。

容器内存与 JVM 堆如何设置?

容器内存不仅包含 Java 堆,还包括:

  • 元空间。
  • 线程栈。
  • 直接内存。
  • Code Cache。
  • JVM 和 native 库。

因此不能把 -Xmx 设置为容器内存上限,应为非堆和系统开销预留空间,并监控容器 RSS。超限后被 cgroup OOM kill(退出码 137、JVM 无异常日志)的机制与排查见操作系统”page cache 与 OOM killer”一节。


四、Kubernetes

Pod、Deployment、Service 分别是什么?

  • Pod:Kubernetes 最小调度单元,包含一个或多个容器。
  • Deployment:管理无状态 Pod 的副本、滚动更新和回滚。
  • Service:为一组 Pod 提供稳定访问地址和负载均衡。

readiness 和 liveness probe 的区别?

探针失败后的含义常见动作
readiness当前不能接收流量从 Service Endpoints 移除
liveness进程可能无法自愈重启容器
startup应用仍在启动启动完成前保护其他探针

不要把短暂的下游故障直接作为 liveness 失败条件,否则可能引发批量重启。

Kubernetes 中服务发布的基本过程?

  1. 构建并推送不可变版本镜像。
  2. 更新 Deployment 镜像版本。
  3. 创建新 Pod,通过 readiness 后接收流量。
  4. 逐步下线旧 Pod。
  5. 观察错误率、延迟和资源指标。
  6. 异常时暂停或回滚。

五、CI/CD 与发布

Maven 生命周期、依赖冲突、BOM 和可重复构建见 构建与依赖管理;测试分层和质量门禁见 测试与代码质量

一条典型 CI/CD 流水线包含什么?

代码检查 → 单元测试 → 构建制品 → 安全扫描
→ 部署测试环境 → 集成测试 → 灰度发布 → 全量发布

构建产物应具备版本号和可追溯信息,同一制品在不同环境间晋级,不要每个环境重新构建。

蓝绿发布、滚动发布、金丝雀发布的区别?

方式特点适用场景
蓝绿发布新旧环境并存,一次切流回滚要求快,但资源成本高
滚动发布分批替换实例常规无状态服务
金丝雀发布少量用户或流量先验证高风险变更和核心服务

数据库变更如何兼容灰度发布?

遵循扩展再收缩:

  1. 先新增字段或表,保持旧代码兼容。
  2. 发布同时兼容新旧结构的代码。
  3. 完成数据回填和验证。
  4. 切换读写逻辑。
  5. 确认无旧版本后再删除旧结构。

不要在同一次发布中直接重命名或删除仍被旧版本使用的字段。

如何设计可回滚的发布?

  • 应用版本和配置都可追溯。
  • 数据库变更向前向后兼容。
  • 消息格式和缓存结构支持版本演进。
  • 明确自动回滚指标和人工决策人。
  • 发布前验证回滚步骤,而不是故障时临时研究。

六、可观测性

日志、指标、Trace 如何分工?

  • 日志:记录离散事件和上下文。
  • 指标:反映趋势、容量和异常。
  • Trace:展示跨服务调用链和各节点耗时。

关键请求应贯穿统一的 Trace ID,日志避免打印密码、令牌和完整个人信息。

服务至少应该监控哪些指标?

可以按四类整理:

  • 流量:QPS、并发数、消息生产速度。
  • 错误:错误率、异常类型、消费失败。
  • 延迟:平均、P95、P99。
  • 饱和度:CPU、内存、线程池、连接池、队列长度。

同时监控业务指标,技术指标正常不代表业务一定正常。


七、Git 版本控制

Git 分支策略

频次 ★★★ · 难度 🟢 · 高频:阿里/字节/腾讯/美团/百度/京东

策略分支结构适用场景特点
Git Flowmaster + develop + feature/* + release/* + hotfix/*版本化产品发布(客户端 App、大型企业产品)流程严谨,但对快速迭代太重
GitHub Flow只有 main + 短生命周期 feature 分支,合入 PR持续部署的 Web 应用简单灵活,维护分支少
Trunk-Based所有人直接在 main 开发 + feature flag 控制功能高频率 CI/CD 团队(Google/Facebook 等)分支寿命 < 1 天,需强 CI/CD 和 feature flag 体系

面试追问:

  • Git Flow 现在过时了吗?→ 对快速迭代的 Web 后端来说确实太重——release 分支冻结期间没人能合入新 feature,降低交付速度。现代团队多用 GitHub Flow(简单)或 Trunk-Based(高频),Git Flow 更适合客户端 SDK/系统软件等有严格发布窗口的项目。
  • merge 和 rebase 的区别?→ git merge 创建合并提交保留分支拓扑,能看到”谁从谁分支”的历史;git rebase 把当前分支的提交在目标分支顶部重放,历史变线性。原则:公共分支用 merge,个人分支用 rebase——已推送到远程的公共分支 rebase 会改写历史,其他人 pull 时冲突。

Git 常用操作

操作场景命令
撤回 commitcommit 后发现忘了加文件或注释错了git reset --soft HEAD^(保留暂存区改动,只撤回提交)
撤回 push推送到远程后发现有问题git reset HEAD^ + git push origin xxx --force-with-lease
临时切换正在开发 A,紧急修复 Bgit stash 暂存当前改动;git stash pop 恢复
挑特定提交只把某几个 commit 搬到当前分支git cherry-pick <commit-hash>
交互式 rebase合并、修改、重排多个 commitgit rebase -i HEAD~3(合并最近 3 个 commit 为 1 个)
查看文件谁改过定位某行代码的最后修改者git blame <file>
二分查找 bug找到引入 bug 的第一个 commitgit bisect start + git bisect bad + git bisect good

常见追问:

  • --force-with-lease--force 的区别?→ --force 直接覆盖远程分支;--force-with-lease 检查远程分支是否被其他人推过新提交(基于你最后一次 fetch 时的 remote ref),更安全。永远不要用裸 --force,至少用 --force-with-lease
  • .gitignore 生效了但文件还在?→ .gitignore 只对未跟踪文件生效,已经被 Git 跟踪的文件需要 git rm --cached <file> 先移除索引再重新提交。