面灵AI→

帆软四面:单机部署服务的卡顿与无规律宕机排查连环追问

轮次
四面
时间
2026-10
来源
牛客网

《面试题目》

技术题

  1. 场景:单机部署的前后端项目,出现两个现象——现象 1:部分用户打开页面卡顿 20 到 60 秒,之后可以恢复;现象 2:服务运行一段时间后无规律宕机,全部用户无法访问,重启服务后恢复。请分析可能原因、定位手段、临时解决方案、根治方案。
  2. 追问:如果是全部用户同时长时间卡顿,过一会又恢复,可能是什么原因?怎么定位?
  3. 追问:除了排队、锁竞争、应用程序侧、中间件故障,还有哪些原因会造成全部用户集体卡顿几十秒?
  4. 追问:服务宕机必须重启才能恢复,过几天又复现,怎么定位问题?
  5. 追问:针对 OOM、死锁、无限递归这些问题,分别使用什么工具或手段定位确认?
  6. 追问:针对上面这些故障,对应的修复方案是什么?

非技术 / 团队氛围类

  1. 从你的角度,你希望团队或公司具备什么样的氛围,愿意留下来;什么状况会让你选择离开?

《参考解析》

现象 1:部分用户卡顿 20 到 60 秒后自行恢复,先按「局部资源被短时占满」这条线排查。 只影响部分用户说明不是应用整体不可用,而是某个共享资源在高峰期或特定路径上被打满,超时后释放又恢复。常见成因有这么几类:JVM 长暂停(大对象或缓存撑爆老年代触发 Full GC,或者元空间/直接内存增长),慢 SQL 或锁等待(某条查询走错索引、被大事务持有的行锁挡住、连接池被占满导致后续请求排队),外部依赖超时(第三方接口、DNS 解析、Redis 大 key 阻塞、磁盘 IO 抖动),以及同步代码块竞争、缓存击穿后大量请求回源、定时任务在高峰期抢 CPU 或带宽。定位顺序是「先对齐时间点,再分层下钻」:把用户反馈的时间戳和监控曲线对齐(CPU、内存、GC、磁盘 IO、连接池、QPS、P95 延迟),确认卡的是应用还是下游;再用 jstat -gcutil 看 GC 频率与老年代占用、jstack 连着抓几次看线程都在等什么、top -H 配 pidstat 看 CPU 热点、慢查询日志和 SHOW PROCESSLIST 看数据库侧。临时方案是止损优先:扩容或临时加机器、把耗时接口降级或限流、清掉异常缓存、重启实例并保留现场。根治要落到根因上——扩连接池并加超时、给慢 SQL 补索引或改成异步、把大 key 拆开、给下游调用加熔断和超时、把定时任务挪到低峰并限制并发。

全部用户同时卡几十秒,说明卡点在「全局唯一」的东西上。 原帖面试官已经点掉了排队、锁竞争、应用侧和中间件故障,剩下的可以往这些方向补:JVM 全局停顿(Full GC、类加载、JIT 去优化)、操作系统层(swap 抖动、内存回收、句柄或进程数打满、负载过高)、磁盘与日志(日志框架同步刷盘、日志切割、磁盘写满、RAID 或云盘 IO 抖动)、网络(带宽跑满、网卡丢包、DNS 解析阻塞、上游负载均衡健康检查抖动)、数据库全表锁(DDL、大事务、备份任务)、以及定时全量任务和缓存集中失效。定位的抓手是把「集体卡顿的起始时刻」和所有全局资源的曲线对齐,再看是不是周期性出现——周期性强基本能锁到定时任务或缓存过期策略,随机出现则更可能是资源泄漏累积后的临界点。

现象 2:无规律宕机且必须重启,本质是「进程已经不可用,但进程本身还在」。 单机上最常见的死法是内存类问题:堆 OOM、元空间撑满、直接内存泄漏、线程数或句柄泄漏,最后被系统 OOM Killer 杀掉或进程僵死;其次是死锁和无限递归导致请求线程全部耗尽;再往下是 CPU 被慢循环打满、磁盘写满导致进程崩溃。定位的关键是事发前就留下证据:启动参数打开 -XX:+HeapDumpOnOutOfMemoryError 和 GC 日志、配置 core dump、把应用日志按天切割并保留足够天数,接上监控记录内存与线程数的趋势。有了这些,复现后就能比较两次宕机前的堆快照、看 OOM 日志里的具体区域、用 jstack 看是否所有线程都卡在同一把锁上。原帖问「过几天又复现怎么定位」,答法就是:不指望复现时人在现场,而是靠趋势监控找增长曲线(内存/线程/句柄/连接数是否单调上升)、靠 dump 对比找堆积对象、靠日志回看第一次报错的位置——通常真正的起点比宕机时间早很多。临时手段是加内存、重启、限流;根治是修泄漏、把无界缓存和有界队列设上限、给递归加深度或改成迭代、给锁加超时和固定加锁顺序。

三类问题的工具要能一一对应,这是这一轮的核心考点。 OOM:先用 -XX:+HeapDumpOnOutOfMemoryError 拿到堆快照,再用 MAT 或 VisualVM 打开看支配树和引用链,jmap -histo 可以快速看哪类对象数量异常;元空间和直接内存的问题堆快照里看不到,要靠 jstat 的 MC/MU 和 NMT、以及 -XX:MaxDirectMemorySize 的配置一起判断。死锁:jstack 会直接打印 Found one Java-level deadlock 并指出互相持有的锁和具体代码行,线上不方便重启可以用 Arthas 的 thread -b 直接找阻塞其他线程的那一个,数据库死锁则看 InnoDB 的 SHOW ENGINE INNODB STATUS。无限递归:日志里通常是 StackOverflowError,jstack 能看到同一段栈帧大量重复,定位到方法后检查递归出口和终止条件,再考虑改成迭代或加深度限制。修复方案可以按类收口:内存问题收敛到参数配置、缓存上限和对象生命周期管理;死锁收敛到加锁顺序、锁粒度和超时重试;递归收敛到终止条件与循环改写;另外都要补上超时、熔断、限流和告警,让下一次故障先被监控发现而不是被用户发现。

最后那道氛围题看着软,其实在筛匹配度。 面试官想知道你对协作方式的偏好,以及你的离职触发点是否和这家公司的现状冲突。答法上先给「愿意留下来」的具体条件——目标清晰、评审和复盘是常态、出问题对事不对人、有明确的技术成长路径;再说「会选择离开」的底线,选那些普遍的、不针对具体公司的点(长期没有反馈、承诺反复变动、靠加班掩盖流程问题)。别把答案说成对上一家公司的抱怨,也别为了讨好而答「什么都能接受」,那会让这一题失去信息量,反而显得没有判断。