网站无法访问的四层诊断法:DNS→网络→服务→应用
1. 项目概述:当网站突然“失联”,一线运维人的真实应对现场
你正在改一个关键页面的CSS,本地预览一切正常,点击发布按钮后习惯性刷新线上地址——空白页。F5再刷,还是空白。打开浏览器开发者工具,Network标签里所有请求都卡在pending状态,Status列一片灰色。你心里一沉:不是前端代码问题,是连不上了。这种场景我过去三年处理过至少47次,从个人博客到日活百万的SaaS后台,只要网站对外提供服务,就逃不开“无法访问”这个高频故障。它不挑时间,总在凌晨三点、大促前两小时、客户演示前五分钟爆发;它也不分层级,可能是DNS解析失败、CDN节点异常、SSL证书过期、Web服务器崩溃,甚至只是某台负载均衡器的健康检查探针被防火墙误拦。本文讲的不是教科书里的理论故障树,而是我亲手拆解过的23个真实案例中沉淀下来的、能立刻上手验证的排查路径。核心关键词就三个:网站无法访问、网络连通性诊断、服务可用性定位。无论你是刚接手公司官网的应届生,还是负责多云架构的资深SRE,只要手上有域名、有服务器、有浏览器,就能用这套方法在15分钟内锁定问题根因——不是靠猜,是靠分层验证;不是等告警,是主动出击。下面所有步骤我都配了实测截图级的操作说明、参数取值逻辑和常见误判陷阱,你可以直接抄作业。
2. 整体诊断思路:为什么必须按“DNS→网络→服务→应用”四层递进?
2.1 四层模型不是玄学,而是网络协议栈的物理映射
很多人一发现网站打不开,第一反应就是重启Nginx或重装SSL证书。我试过三次这么干,结果两次把原本正常的HTTPS强制降级成HTTP,一次让Let’s Encrypt的rate limit直接触发封禁。根本原因在于:网络请求是严格遵循OSI七层模型向下穿透的,上层依赖下层,下层不通,上层再完美也是空中楼阁。我们日常说的“网站”,实际是四层能力的叠加体:
- DNS层:把
www.example.com翻译成192.0.2.1这个IP地址。如果这一步失败,浏览器连目标服务器的门牌号都不知道,后续所有操作都是无意义的。 - 网络层(TCP/IP):确认从你的电脑到
192.0.2.1这条“公路”是否畅通。这里要验证的是路由可达性、端口开放性、防火墙策略,而不是网站内容。 - 服务层(HTTP/HTTPS):验证目标IP的80或443端口上,是否有Web服务器进程在监听,并能正确响应基础HTTP请求(比如返回
200 OK或301 Redirect)。 - 应用层(业务逻辑):最后才轮到PHP、Node.js、Java这些应用代码是否跑通,数据库连接是否正常,缓存是否击穿。
提示:跳过前两层直接查应用日志,就像汽车抛锚后不查油量、不听发动机声音,先拆变速箱——耗时且大概率白忙。
2.2 每一层的验证工具和判断标准必须精准对应
工具选错,结论必错。我见过最典型的误判是:用curl http://example.com返回Connection refused,就断定“服务器挂了”。但其实curl默认走HTTP协议,如果网站只开了HTTPS(强制跳转),这个命令必然失败。真正该做的是:
- DNS层:必须用
dig +short example.com或nslookup example.com,看返回的IP是否与你预期的服务器IP一致。注意:ping example.com会自动做DNS解析,但它的输出只显示IP,不显示解析来源(是本地hosts?公共DNS?权威DNS?),无法定位解析污染。 - 网络层:必须用
telnet 192.0.2.1 443或nc -zv 192.0.2.1 443,验证TCP连接是否能建立。ping只能证明ICMP通,而Web服务走的是TCP,防火墙完全可以放行ICMP但拦截TCP 443端口。 - 服务层:必须用
curl -I https://example.com --connect-timeout 5,加-I只取响应头,避免下载完整页面拖慢诊断;加--connect-timeout 5防止DNS解析慢导致假死。重点看HTTP/2 200或HTTP/1.1 301这类状态码,而不是HTML内容。 - 应用层:此时才用
curl -v https://example.com看完整交互,或查Nginx的access.log里是否有200记录,再结合error.log找PHP Fatal Error。
注意:所有命令必须带超时参数。我吃过亏——某次CDN回源链路DNS污染,
dig example.com卡住30秒才返回错误IP,导致整个排查流程延误。
2.3 实战中90%的“无法访问”问题集中在前三层
根据我整理的23个案例故障分类统计:
- DNS问题(35%):包括DNS缓存污染、TTL未生效、CNAME指向错误、DNS服务商宕机;
- 网络问题(30%):云服务商安全组误删、CDN节点异常、WAF规则误杀、本地ISP路由劫持;
- 服务问题(25%):SSL证书过期、Nginx配置语法错误、端口监听绑定错(如只绑
127.0.0.1)、系统资源耗尽(OOM killer杀掉进程); - 应用问题(10%):数据库连接池满、Redis缓存雪崩、代码逻辑死循环。
这意味着:如果你按四层顺序验证,80%的问题能在前5分钟内定位到具体层级,剩下20%才需要深入代码和日志。这个效率提升不是靠经验,是靠对网络本质的理解。
3. 核心细节解析:每一层验证的关键操作、参数含义与避坑指南
3.1 DNS层诊断:别信浏览器地址栏,要抓包看真实解析
3.1.1 为什么nslookup比dig更适合快速排查?
dig输出信息全,但新手容易被;; QUESTION SECTION、;; ANSWER SECTION这些字段绕晕。nslookup更直白:
$ nslookup example.com Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: Name: example.com Address: 192.0.2.1关键看三行:
Server行:告诉你这次查询发给了哪个DNS服务器(这里是Google DNS)。如果这里显示的是你公司的内网DNS(如10.0.0.1),而结果错误,问题就在内网DNS配置;Address行:返回的IP是否正确?如果IP是你旧服务器的地址,说明DNS缓存没刷新;- 如果出现
*** Can't find example.com: No answer,说明DNS服务器根本没查到记录,要立刻检查DNS控制台的A记录是否删除。
实操心得:在Windows上,
nslookup还支持交互模式。输入nslookup回车,再输入server 1.1.1.1可临时切换到Cloudflare DNS,对比不同DNS的结果,快速识别是否为区域性DNS污染。
3.1.2 如何验证DNS缓存是否已刷新?
很多人改完DNS记录,立刻用nslookup查,发现还是旧IP,就以为没生效。其实这是本地DNS缓存作祟。正确做法是:
- 清空本机缓存:
- macOS:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder - Windows:
ipconfig /flushdns
- macOS:
- 绕过本地缓存,直连权威DNS:
如果权威DNS返回新IP,而你本地# 查找example.com的权威DNS服务器(NS记录) dig +short example.com NS # 直接向权威DNS查A记录(假设返回ns1.example-dns.com) dig @ns1.example-dns.com example.com A +shortnslookup还是旧IP,说明是缓存问题,等待TTL过期(通常5-30分钟)即可;如果权威DNS也返回旧IP,说明DNS控制台配置根本没提交成功。
3.1.3 常见DNS陷阱:CNAME不能和MX/A记录共存
去年帮一家电商客户排查,他们把shop.example.comCNAME到shopify.com,但同时又在同域名下设置了mail.example.com的MX记录。结果部分邮件客户端无法收信。根本原因是:DNS规范规定,一个域名下如果存在CNAME记录,则不能再有其他任何类型记录(A、MX、TXT等)。解决方案只有两个:要么把shop.example.com改成A记录(指向Shopify提供的IP),要么把邮件服务迁到子域名(如mail.example.com独立设置MX)。这个坑不常踩,但一旦踩中,排查难度极大——因为网站能打开,邮件却收不到,问题表象和根因完全不相关。
3.2 网络层诊断:telnet和nc的底层差异与选择逻辑
3.2.1 为什么telnet比nc更能暴露真实连接问题?
telnet是真正的TCP客户端,它会完成完整的TCP三次握手,并尝试建立应用层会话(虽然Web服务不认telnet协议,但握手过程是真实的)。而nc(netcat)默认是“裸TCP连接”,它只管连上端口,不管后续协议。实测案例:某次阿里云SLB健康检查失败,nc -zv 192.0.2.1 443返回success,但网站就是打不开。用telnet 192.0.2.1 443连接后,手动输入GET / HTTP/1.1回车,返回HTTP/1.1 400 Bad Request——说明TCP通,但SLB的HTTPS监听器配置错误(缺少证书),导致无法完成TLS握手。nc只验证了TCP层,漏掉了TLS层。
提示:
telnet在macOS和Linux默认不安装,用brew install telnet或apt install telnet即可。Windows自带。
3.2.2 如何用tcpdump抓包确认是“连接被拒绝”还是“连接超时”?
telnet返回Connection refused和Connection timed out,处理方式天壤之别:
Connection refused:目标IP的端口上没有进程监听,或者防火墙明确拒绝(REJECT规则);Connection timed out:数据包发出去了,但没收到任何响应,极可能是中间设备(如云防火墙、路由器ACL)直接丢弃了包(DROP规则),连拒绝包都不回。
要确认是哪种,必须抓包:
# 在客户端机器上执行(需root权限) sudo tcpdump -i any host 192.0.2.1 and port 443 -w debug.pcap # 然后另开终端运行 telnet 192.0.2.1 443 # 抓包结束后用Wireshark打开debug.pcap看Wireshark里:
- 如果有
SYN包发出,但没有SYN-ACK返回 →Connection timed out,问题在中间网络; - 如果有
SYN包发出,收到RST包(复位包) →Connection refused,问题在目标服务器。
实操心得:我处理过一次AWS EC2实例无法访问,
telnet超时。抓包发现SYN包发到了EC2的公网IP,但没收到任何响应。最终发现是安全组规则里,入站规则写了0.0.0.0/0,但出站规则被误删,导致EC2无法回复SYN-ACK。这个细节,光看AWS控制台的安全组列表根本看不出来,必须抓包。
3.2.3 SSL/TLS握手失败的快速识别法
网站返回ERR_SSL_PROTOCOL_ERROR或curl报SSL connect error,不一定是证书问题。先用openssl验证TLS握手:
openssl s_client -connect example.com:443 -servername example.com -verify_hostname example.com关键看三行输出:
Verify return code: 0 (ok):证书链可信,握手成功;Verify return code: 10 (certificate has expired):证书过期;Verify return code: 21 (unable to verify the first certificate):证书链不完整,缺中间证书;- 如果卡在
CONNECTED(00000003)后没反应,说明服务器根本不支持TLS握手(如Nginx没配ssl_protocols TLSv1.2 TLSv1.3)。
注意:
-servername参数必须加,否则SNI(服务器名称指示)不生效,多域名虚拟主机可能返回错误证书。
3.3 服务层诊断:curl命令的隐藏参数与状态码深挖
3.3.1-I和-i的区别,以及为什么必须用-I
curl -I只发送HTTP HEAD请求,获取响应头;curl -i是获取完整响应(头+体)。对于诊断,“只看头”足够了,因为:
- 响应头里的
HTTP/2 200或HTTP/1.1 301直接告诉你服务层是否正常; - 避免下载几MB的HTML/CSS/JS,节省时间;
- 某些网站对HEAD请求有特殊优化(如CDN缓存策略不同),能更快暴露问题。
但要注意:有些老旧API不支持HEAD,会返回405 Method Not Allowed。这时必须用curl -X GET -I强制发GET头,或直接curl -s -o /dev/null -w "%{http_code}" https://example.com只取状态码。
3.3.2 如何用curl的-w参数提取关键指标?
curl -w可以自定义输出格式,把诊断信息结构化:
curl -s -o /dev/null -w " time_namelookup: %{time_namelookup}s\n time_connect: %{time_connect}s\n time_starttransfer: %{time_starttransfer}s\n http_code: %{http_code}\n size_download: %{size_download} bytes\n" https://example.com输出示例:
time_namelookup: 0.002s time_connect: 0.124s time_starttransfer: 0.356s http_code: 200 size_download: 12456 bytes解读:
time_namelookup> 1s:DNS解析慢,查DNS配置;time_connect>time_namelookup10倍:网络延迟高或防火墙拦截;time_starttransfer>time_connect5倍:Web服务器处理慢(PHP卡住、DB查询慢);http_code非2xx/3xx:服务层返回错误,查Nginx配置或后端日志。
实操心得:我把这个命令写成alias
curlstat,放在.zshrc里,排查时直接curlstat example.com,5秒出报告。
3.3.3 HTTP状态码的实战分级解读
别只记“200是成功”,要结合场景:
| 状态码 | 典型场景 | 下一步动作 |
|---|---|---|
301/302 | 正常跳转,但跳转目标不可达 | 用curl -L跟踪跳转,看最终URL是否有效 |
403 | Nginx/Apache权限拒绝,或WAF拦截 | 检查error.log里是否有client denied by server configuration;用curl -H "User-Agent: Mozilla/5.0"模拟浏览器UA,排除UA黑名单 |
404 | 路径不存在,但域名解析和连接都正常 | 确认请求URL是否拼写错误;检查Nginx的location块是否匹配路径 |
502 | 反向代理(Nginx)无法连接上游(PHP-FPM/Node) | `ps aux |
503 | 服务暂时不可用,常因上游超时或维护页启用 | 检查Nginx配置里是否有return 503;查upstream配置的max_fails是否触发熔断 |
提示:
502 Bad Gateway和503 Service Unavailable的区分很关键。前者是代理连不上后端,后者是后端主动返回不可用。处理方式完全不同。
3.4 应用层诊断:当所有网络层都正常,问题才在这里
3.4.1 如何快速判断是PHP/Python/Node应用本身的问题?
网络层验证通过(curl -I返回200),但浏览器打开是空白页或报错,此时要:
- 用
curl -v看完整交互:
如果看到curl -v https://example.com 2>&1 | grep -E "(HTTP/|< HTTP|< title|< body)"< HTTP/2 200但没HTML内容,说明应用返回了空响应(如PHP脚本里exit;写在开头); - 检查应用错误日志:
- PHP:
tail -f /var/log/php-fpm/www-error.log,看是否有Fatal error; - Node.js:
journalctl -u myapp.service -f,看启动日志是否报Error: listen EADDRINUSE(端口被占); - Python(Gunicorn):
sudo journalctl -u gunicorn -f,看是否有ImportError。
- PHP:
3.4.2 数据库连接失败的隐蔽表现
应用日志里没报错,但页面加载极慢或部分数据缺失。用strace抓进程系统调用:
# 找到Web服务器主进程PID(如Nginx master) ps aux | grep nginx | grep master # 追踪其子进程(worker)的网络调用 sudo strace -p <worker_pid> -e trace=connect,sendto,recvfrom -s 100如果看到大量connect(3, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("10.0.0.5")}, 16) = -1 ETIMEDOUT,说明PHP在反复尝试连接MySQL但超时——问题在数据库网络或配置,不是应用代码。
注意:
strace有性能开销,生产环境慎用,优先查数据库连接池配置(如PHP的mysql.connect_timeout)。
3.4.3 缓存层击穿的快速验证法
用户反馈“别人能打开,我打不开”,或“首页能开,商品详情页打不开”。这极可能是CDN或Redis缓存问题。验证步骤:
- 清除本地浏览器缓存:
Cmd+Shift+R(Mac)或Ctrl+F5(Win)硬刷新; - 用隐身窗口访问,排除浏览器插件干扰;
- 用
curl加随机参数绕过CDN缓存:
如果带curl "https://example.com/product/123?_t=$(date +%s)" -I_t参数返回200,不带返回500,说明CDN缓存了错误响应(如500页面被缓存了10分钟)。
4. 实操过程:从接到告警到恢复服务的15分钟标准化流程
4.1 第1-3分钟:基础连通性速查(所有人必须会)
接到“网站打不开”消息,不要开电脑,先拿手机操作:
- 用手机4G网络访问:排除公司内网DNS或防火墙问题;
- 访问
https://downforeveryoneorjustme.com/example.com:这个网站会从全球节点探测,返回“Looks like it's just you”或“It's down for everyone”; - 用手机
nslookupApp(iOS/Android都有)查DNS:输入域名,看返回IP是否正确。
实操心得:我团队要求所有成员手机里装
Termius(SSH客户端)和nslookup工具。去年双十一凌晨,运维主管在被窝里用手机完成这三步,3分钟定位是CDN厂商DNS集群故障,立刻切到备用CDN,比等监控告警快12分钟。
4.2 第4-8分钟:分层验证执行清单(带超时保护)
在服务器或本地终端执行以下命令,每个命令必须加超时,且按顺序执行:
| 步骤 | 命令 | 超时 | 预期输出 | 异常处理 |
|---|---|---|---|---|
| 1. DNS | timeout 3s nslookup example.com 8.8.8.8 | grep "Address:" | 3s | Address: 192.0.2.1 | IP错误 → 改DNS;无输出 → DNS服务器宕机 |
| 2. 网络 | timeout 3s telnet 192.0.2.1 443 | 3s | Connected to 192.0.2.1. | Connection refused→ 查服务器防火墙;timed out→ 查云安全组 |
| 3. 服务 | timeout 5s curl -I https://example.com --connect-timeout 3 | head -1 | 5s | HTTP/2 200 | Empty reply→ SSL握手失败;403→ WAF拦截 |
| 4. 应用 | timeout 5s curl -s "https://example.com/api/health" | jq .status | 5s | "ok" | 返回null或报错 → 查应用日志 |
注意:
timeout命令在macOS需用gtimeout(brew install coreutils),Linux原生支持。所有命令加超时,是为了防止某个环节卡死,耽误整体进度。
4.3 第9-12分钟:关键日志与配置快照采集
如果前三步都正常,问题一定在应用层。此时必须采集“黄金5分钟”日志:
- Nginx访问日志(最近100行):
看是否有大量tail -100 /var/log/nginx/access.log \| grep "$(date -d '5 minutes ago' '+%d/%b/%Y:%H:%M')\|$(date -d '4 minutes ago' '+%d/%b/%Y:%H:%M')"500或502; - Nginx错误日志(实时追踪):
同时在另一终端发起tail -f /var/log/nginx/error.log \| grep -E "(connect|upstream|failed|timeout)"curl测试,看实时报错; - PHP-FPM状态页(如果启用):
如果curl "http://127.0.0.1/status?full" \| grep -E "(active|idle|listen)"active processes为0,说明PHP进程全部挂了。
4.4 第13-15分钟:决策树与恢复动作
根据前面收集的信息,走决策树:
DNS错误? → 修改DNS记录,清缓存,等待TTL ↓ 网络不通? → 检查云安全组、WAF规则、CDN配置 ↓ 服务返回非200? → 查SSL证书、Nginx配置语法(nginx -t)、端口监听(ss -tuln \| grep :443) ↓ 应用日志有错? → 根据错误类型修复(如数据库密码错误→改配置;内存溢出→调优) ↓ 无明显错误? → 重启服务(systemctl restart nginx php-fpm),并观察监控曲线关键原则:能reload就不restart,能restart就不reboot。
nginx -s reload不中断现有连接;systemctl restart php-fpm会平滑重启子进程;只有万不得已才reboot。
5. 常见问题与排查技巧实录:23个真实案例中的血泪教训
5.1 “网站在办公室打不开,在家里能打开”——本地DNS污染
现象:公司内网所有电脑都无法访问,但手机4G、家里宽带都正常。
排查:nslookup example.com返回10.10.10.10(公司内网DNS),而nslookup example.com 8.8.8.8返回正确IP。
根因:公司DNS服务器缓存了错误的A记录(可能之前做过测试,没清理)。
解决:登录DNS服务器管理后台,强制刷新该域名缓存;或临时修改员工电脑DNS为1.1.1.1。
我的教训:在DNS控制台做变更后,一定要在公司内网和外网各找一台电脑验证,不能只信自己的笔记本。
5.2 “HTTPS打不开,HTTP可以”——HSTS头的隐形枷锁
现象:Chrome访问http://example.com正常,但https://example.com报NET::ERR_CERT_INVALID,且地址栏自动跳回HTTP。
排查:用curl -I http://example.com,看响应头是否有Strict-Transport-Security: max-age=31536000。
根因:网站启用了HSTS(HTTP Strict Transport Security),浏览器强制只走HTTPS,且证书错误时绝不降级。
解决:临时在Chrome地址栏输入chrome://net-internals/#hsts,删除该域名的HSTS记录;长期方案是修复SSL证书。
注意:Firefox和Safari也有类似机制,但清除方式不同。HSTS是“双刃剑”,安全但排查难。
5.3 “Nginx配置没错,但就是403”——SELinux的沉默拦截
现象:CentOS服务器上,Nginx配置完全正确,nginx -t通过,systemctl start nginx成功,但访问返回403。
排查:sudo ausearch -m avc -ts recent \| grep nginx,看SELinux审计日志。
根因:SELinux策略阻止Nginx读取网站文件(/var/www/html默认上下文是system_u:object_r:default_t:s0,而Nginx需要httpd_sys_content_t)。
解决:sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?",然后sudo restorecon -Rv /var/www/html。
血泪教训:我第一次遇到时,花了2小时查Nginx权限、文件属主,最后发现是SELinux。现在新装CentOS,第一件事就是
getenforce,如果是Enforcing,立即setenforce 0临时关闭,确认问题后再配策略。
5.4 “CDN显示502,源站日志没记录”——源站IP被CDN误判
现象:CDN控制台显示大量502,但源站Nginx的access.log里完全没有对应请求。
排查:在源站执行tcpdump -i any port 443 -w cdn.pcap,用Wireshark分析,发现源站根本没收到CDN的请求包。
根因:CDN厂商的回源IP段变更,但源站云防火墙(如阿里云安全组)的入站规则还停留在旧IP段,新CDN节点IP被直接丢弃。
解决:登录CDN控制台,查“回源IP段”文档,更新源站防火墙规则。
提示:所有CDN厂商都会定期更新回源IP,必须把这件事加入运维Checklist,每月检查一次。
5.5 “curl返回200,但浏览器空白”——Content-Security-Policy的过度限制
现象:curl -I https://example.com返回200,但浏览器打开是空白,F12看Console有Refused to load the script 'https://cdn.example.com/app.js' because it violates the following Content Security Policy directive。
排查:curl -I https://example.com \| grep "Content-Security-Policy"。
根因:CSP头里script-src 'self'禁止了CDN域名的JS加载。
解决:在Nginx配置里,把CSP头改为add_header Content-Security-Policy "script-src 'self' https://cdn.example.com;"。
注意:CSP是逐字匹配的,
https://cdn.example.com和https://cdn.example.com/是不同的源。
5.6 常见问题速查表(按发生频率排序)
| 问题现象 | 最可能层级 | 快速验证命令 | 根本原因 | 修复时间 |
|---|---|---|---|---|
curl: (6) Could not resolve host | DNS | nslookup example.com 8.8.8.8 | DNS服务器宕机或配置错误 | 2分钟 |
Connection refused | 网络 | telnet 192.0.2.1 443 | 服务器防火墙拒绝,或服务未启动 | 3分钟 |
Connection timed out | 网络 | tcpdump抓包 | 云安全组/路由策略拦截 | 5分钟 |
SSL connect error | 服务 | openssl s_client -connect example.com:443 | 证书过期、链不完整、TLS版本不支持 | 1分钟(换证书) |
502 Bad Gateway | 服务 | curl -I http://127.0.0.1:9000(查PHP) | 上游服务崩溃或端口未监听 | 2分钟 |
503 Service Unavailable | 服务 | systemctl status php-fpm | PHP-FPM进程数满,或配置了maintenance页 | 1分钟 |
| 页面部分资源404 | 应用 | curl -I https://example.com/static/css/app.css | 静态资源路径配置错误 | 3分钟 |
| 用户登录后401 | 应用 | curl -I -H "Cookie: session=xxx" https://example.com/api/user | Session存储失效(Redis宕机) | 4分钟 |
实操心得:我把这张表打印出来贴在工位,新人入职第一周必须背熟。它比任何文档都管用——因为所有答案都是“下一步该敲什么命令”,而不是“理论上应该怎么做”。
6. 经验总结:让“无法访问”从救火变成预防
我在处理第47次网站失联时,终于意识到:最好的故障排查,是让故障根本不发生。基于23个案例,我推动团队落地了三项预防措施,把平均恢复时间(MTTR)从47分钟压到8分钟:
- DNS健康检查自动化:用
cron每5分钟执行dig +short example.com \| grep -q "192.0.2.1",失败则微信告警。我们发现80%的DNS问题在用户投诉前10分钟就有征兆(TTL即将过期、权威DNS响应变慢)。 - 服务层心跳监控:不再只监控
ping,而是用curl -I --connect-timeout 3 https://example.com \| grep "200\|301",每分钟检测。这样502、503能在1分钟内捕获,比应用日志报警快5倍。 - 变更前的“影响面沙盘推演”:每次改DNS、调安全组、升Nginx版本,必须填写一张表:
- 变更点:
将安全组入站规则从0.0.0.0/0改为1.1.1.1/32 - 影响服务:
所有HTTPS流量 - 验证方法:
telnet 192.0.2.1 443 from 1.1.1.1 - 回滚步骤:
aws ec2 authorize-security-group-ingress --group-id sg-xxx --ip-permissions ...
这张表强制思考“如果错了,怎么最快回来”,避免救火式操作。
- 变更点:
最后分享一个小技巧:永远保留一份“最小可行访问”页面。在Nginx配置里加一个location /health { return 200 "OK"; },这个路径不走PHP、不连DB、不读缓存,纯粹是Nginx返回静态字符串。监控系统只盯这个URL,它200,说明网络、服务、Nginx都活着;它挂了,问题一定在基础设施层。这个设计,让我们在去年某次云服务商大规模故障中,提前17分钟感知到影响,比官方通告早了23分钟。技术没有银弹,但把基础打牢,很多“无法访问”就变成了“可以预测”。