故障排查策略
本页给出一套通用、系统化的方法,帮助你在使用Caddy时自行解决大多数问题(不依赖AI)。当你在论坛求助时,我们也建议采用类似步骤。很多情况下,通过严谨思考,你可以自己回答问题或修复问题。
你知道什么?
你可能暂时不知道问题是什么、原因是什么、怎么修复。那就先从你确定知道的事实开始。
你的预期
把预期明确说出来(口头、心里、或写下来都行)。表达要具体、可验证,不要有歧义。最好还能解释你为什么这样预期。
“它应该能工作”不是一个好的预期。
“我请求这个URI时预期返回301重定向”就好得多。
当前行为
观察实际发生了什么。到底发生了什么?与预期有哪些差异?把已知事实整理出来。
“它不工作”既无帮助也很偷懒;除非你前面已经详细定义了“它不工作”具体指什么,否则尽量不要这样说。
“我预期301,但实际是200;不过响应里有Server: Caddy头”就更有价值,因为它同时表达了预期、现实、差异,以及一个额外事实:请求至少已经到达某个Caddy实例。
日志
Caddy日志里有什么?默认会输出到启动进程的终端。如果你是以系统服务等“后台方式”运行,日志可能在别处。
注意:HTTP请求日志(access log)和进程日志不同;access log需要在配置中显式开启。
如果还没开,也可以考虑开启DEBUG级别日志。
无论如何,排查第一步之一就是看日志,而且是看完整上下文。单独一行日志通常价值很低。收集比你认为更多的日志,并在整个排查过程中保留。
日志里有没有线索?
识别并质疑假设
继续之前,必须强调:质疑自己的假设非常关键。我们都会基于习惯和预期做假设。部署越复杂,假设就越多。
例如常见假设:重新编译Caddy后直接运行caddy就会执行新代码。只有当你编译出的二进制覆盖了$PATH中的那个caddy时才成立。多数情况下应执行./caddy。
再比如Docker部署:你不仅要重建镜像,还要确保运行的就是新镜像,这会引入更多假设。
很多提问和“bug报告”最终都不是Caddy本身的问题,而是外部系统或网络配置问题。比如你连不上Caddy但进程明显在运行,你可能会假设“不是DNS”;提示:它经常就是DNS。
甚至“我已经reload了配置”也常常只是误以为。请在每一层都做验证,保持流程严谨。
复现行为
这是关键步骤,而且常常会在这个过程中直接解决问题:让问题再次出现。
更具体地说:用尽可能小的场景复现。移除不必要的配置、部署步骤和环境因素,直到问题消失。
常见策略是一次只移除一个因素并重试,直到问题消失。最后移除的那个因素大概率就是原因,或者(再次质疑假设)它与之前移除的某个因素组合后才触发问题。再逐步加回去验证。
另一种策略是每轮砍掉约一半因素,问题消失后再对那一半继续二分。这类似二分查找,常更快。
你也可以反过来:不是删减,而是从最小配置逐步往上加,每次都重试,直到问题出现。
很多时候,仅靠这个过程就能定位原因,并且修复方案会变得明显。即便还没修好,至少你能得到“最小复现步骤”。
探索行为
当你有了稳定复现步骤,就具备诊断根因的条件了。接下来是实验(如果熟悉代码也可以读代码)。
如果你还无法解释原因,就主动改变行为。每次做一个小改动再试。例如配置里有正则,就先简化它,甚至先去掉它,观察是否出现“接近预期”的变化。即使结果不是最终想要的,也能缩小范围到正则或配置本身。
在探索中留意“什么有效、什么无效”的模式,它会把你引向解决方案。
如果你找到了方案,再判断它是否是bug。有时并不明显,这时可以带着实验过程发issue,请维护者判断。
如果最终不是bug,也很好:你解决了问题,并且获得了新的理解。
也欢迎把你的排查经验发到论坛,帮助遇到同类问题的人。