第4章 异常处理与错误日志
异常处理与错误日志是生产环境稳定运行的基石。面试官通过本章考察候选人对异常机制的理解深度、日志等级的工程化设计能力、以及错误监控的实战经验。掌握结构化回答框架,让面试官看到你的「故障免疫力」。
异常处理黄金法则:及时捕获 · 准确记录 · 合理转化 · 快速失败 · 优雅降级
知识结构:PSR-3 日志等级对照表
| 等级 | 名称 | 典型使用场景 | 生产告警 |
|---|---|---|---|
| DEBUG | 调试 | 开发环境 SQL 查询、变量值输出 | ❌ |
| INFO | 信息 | 正常业务流程:登录、下单、支付回调 | ❌ |
| NOTICE | 通知 | 正常但需关注:缓存失效、兜底策略触发 | ❌ |
| WARNING | 警告 | 潜在风险:重试、降级、限流触发 | ✅ 实时 |
| ERROR | 错误 | 运行时需处理:DB 连接失败、API 超时 | ✅ 实时 |
| CRITICAL | 严重 | 核心功能不可用:订单服务宕机 | ✅ 电话+群 |
| ALERT | 警报 | 需人工立即介入:磁盘写满、OOM | ✅ 电话+群 |
| EMERGENCY | 紧急 | 系统整体不可用:服务器崩溃 | ✅ 全员 |
面试加分:主动说出「我按 PSR-3 规范设计日志等级,WARNING 以上对接实时告警,INFO 用于业务审计,DEBUG 仅开发环境开启」,体现工程化和运维思维。
问答卡片 ① 异常处理机制
面试问题:请谈谈PHP中的异常处理机制,以及你在项目中如何设计异常处理?
面试官考察点:① 对异常体系的理解深度 ② 工程化设计能力 ③ 是否具备统一异常处理意识
回答框架:异常分类 → 分层捕获 → 自定义异常 → 统一响应
示例回答:我按业务异常与系统异常分类,使用 try-catch 分层捕获,自定义 BaseException 基类继承 \Exception,统一记录完整上下文日志并返回规范 JSON 响应,通过 Sentry 实时告警。
可能追问:① 业务异常和系统异常如何区分? ② 如何处理未捕获异常? ③ 自定义异常类如何设计继承链?
避坑提醒:不要吞没异常(空 catch),不要在 catch 中只写 log 不处理;区分「该抛的异常」和「该吞的异常」。
问答卡片 ② 日志系统设计与等级规范
面试问题:如何设计 PHP 项目的日志系统?日志等级如何划分?
面试官考察点:① 日志体系设计能力 ② 运维意识 ③ 是否了解行业规范
回答框架:等级划分 → 存储方案 → 格式规范 → 轮转策略
示例回答:采用 PSR-3 标准配合 Monolog,按日切割存储至 OSS,统一 JSON 格式包含 trace_id、模块、耗时。WARNING 以上对接钉钉群告警,ERROR 以上触发电话告警,INFO 用于业务审计。
可能追问:① 日志写入如何避免阻塞业务? ② 日志文件膨胀怎么处理? ③ 敏感信息如何脱敏?
避坑提醒:严禁记录明文密码/身份证号;日志目录需设置磁盘限额;切勿将 DEBUG 日志带到生产环境。
问答卡片 ③ 错误监控与生产排查
面试问题:生产环境出现 500 错误,如何快速定位和排查?
面试官考察点:① 问题排查实战能力 ② 监控体系理解 ③ 链路追踪意识
回答框架:监控定位 → 日志查询 → 链路追踪 → 根因分析
示例回答:先查 Sentry 错误聚合按频率排序定位异常接口,再根据 trace_id 到 ELK 搜索完整日志链路,分析请求参数与堆栈,最后结合 APM 看 DB 慢查询或 Redis 异常,定位后灰度修复。
可能追问:① 如何区分网络层错误与应用层错误? ② ELK 中日志字段如何设计? ③ 没有 trace_id 怎么处理?
避坑提醒:不要只看单条日志,要拉时间窗口聚合;注意区分业务异常(如参数校验失败)和系统异常;排查时先确认自身服务,再依赖上游。
核心原则:异常处理要「抓得住、记得住、报得出、查得到」。面试时展示从捕获到闭环的完整链路思维,比单独讲语法高出一个层级。
项目案例:电商平台订单服务错误监控体系
| 维度 | 内容 |
|---|---|
| 项目名称 | 电商平台订单服务错误监控与可观测性体系 |
| 业务背景 | 618 大促期间订单量激增,需在分钟级发现和定位异常,保障 99.99% 可用性 |
| 规模指标 | 峰值 QPS 5000+,日订单量 200 万+,30+ 服务节点,日均日志量 150 GB |
| 技术栈 | PHP 8.1 + Laravel + Sentry + ELK + Prometheus + Grafana + RabbitMQ |
| 核心难点 | ① 分布式环境 trace_id 跨服务透传 ② 日志量大海捞针 ③ 告警噪音过多 |
| 面试高频追问 | ① trace_id 如何通过 HTTP 和 MQ 透传? ② 告警阈值如何设定避免误报? ③ 日志量过大如何降本增效? |
| 可迁移回答话术 | 「在中间件入口生成 trace_id 注入上下文,通过 HTTP 头 + MQ 消息属性透传,确保全链路可回溯;告警基于 P99 历史数据动态基线计算,配合 Grafana 看板实现分钟级发现;冷日志归档至 OSS 低频存储,热日志保留 7 天。」 |
⛔ 常见踩坑:项目案例切忌只讲业务功能,要突出「稳定性设计」。面试官在异常处理章节,想听的是你如何让系统「扛得住、查得清、恢复快」。
背诵关键句:「异常处理不是 catch 后写日志就结束,而是从分类、捕获、记录、告警到根因分析的完整闭环。」—— 这句话放在每个回答结尾,都会让面试官点头。