网站打不开或者接口频繁超时,用户侧的表现往往都是刷不出页面,但背后的原因可能千差万别。与其反复刷新或者盲目重启,不如从访问链路、服务器资源、应用服务层再到数据存储层,由外向内逐段排查。这样不仅能更快定位问题,也能避免在无关联的环节白白耗费时间。
网站出问题时,先别急着登服务器,第一步是判断故障到底出在访客侧、线路侧,还是站点本身。最直接的办法是切换网络环境做对比验证,比如关掉Wi-Fi改用手机流量访问,或者让异地的同事帮忙打开页面。换网络后如果访问正常,问题大概率出在本机网络或出口宽带上;如果只有某个地区访问不了,那可能涉及骨干线路波动,或者DNS缓存还没同步到最新的解析结果。
在本地电脑打开命令行,输入nslookup 你的域名,核对返回的IP地址是否和服务器当前使用的IP一致。如果解析结果为空,或者仍旧指向一个已经停用的旧IP,通常说明A记录被改过,或者TTL值设得太长,导致全球DNS节点里的旧缓存迟迟没刷新。此时登录域名注册商后台逐条核对记录,同时也要检查CDN控制台里的回源地址是否还指向前一台过期源站。个别地区访问异常,多见于该地区边缘节点还未清除旧源站缓存,手动刷新CDN缓存通常能立刻缓解症状。
有时候用ping命令能收到服务器回应,但浏览器始终卡在“正在连接”,这时候八成是端口被拦住了。先在本地运行telnet 服务器IP 443 或者 nc -vz 服务器IP 443,如果长时间超时或者直接提示拒绝连接,就要去云平台的防火墙控制台,确认80和443端口已经加入入方向放行规则。排查时有一个实用技巧:临时把一个非标准端口(比如8443)也放行,并从外部测试该端口,如果这个端口能通而443不通,基本就能断定是安全组策略或运营商封禁了特定端口,而不是服务器本身宕机。
当网络层与端口都正常,但网站响应依旧缓慢,或出现间歇性超时,下一步要做的是查看服务器自身的身体状况。CPU被占满、内存耗尽、磁盘写满或者带宽被占满时,新进来的请求都会在队列里排队,用户体验就是页面一直转圈或者中途断连。依次执行top、free -h和df -h三条命令,能迅速对系统整体占用情况有个基本判断。
在top界面按大写P让进程按CPU占用率排序,重点观察排在最前面的几个进程。比较常见的原因有三种:服务器被植入挖矿程序、数据库慢查询不断堆积,以及没有做频控的爬虫持续抓取页面。把可疑的进程ID记下来,再去核对Web访问日志,往往能找到对应的来访IP和请求路径。举个例子,某个API接口被外部脚本每秒调用数十次,日志里会完整记录该IP的请求轨迹,这时直接在防火墙或Web服务器中加入封禁规则,CPU负载通常几分钟内就会降回正常水位。
磁盘使用率超过80%是需要警惕的信号。日志文件、上传临时目录或者Session存放目录一旦写满,程序就会无法落盘,网站直接跳出500错误。平时应该配置好日志轮转策略,比如通过Logrotate按天切割并清理七天前的旧日志。如果内存吃紧,先定位是否有进程存在内存泄漏,比如长期运行的Java应用或Python脚本,必要时适当调低PHP-FPM或Tomcat的并发处理参数,临时开启Swap空间也能争取一些缓冲时间,但要注意这只适合应急,不能长期依赖。
资源有富余、网络也通畅时,故障大概率藏在应用服务自身。先确认Nginx、Apache或者Tomcat这些Web服务是否处于正常运行状态,systemctl status nginx 或者 ps -ef | grep nginx 能快速给出结果。服务进程虽然活着,不代表处理请求就一定正常,还需要关注进程数是否已经撞上上限。
当Nginx的worker_connections、Apache的MaxRequestWorkers或者PHP-FPM的pm.max_children达到上限时,新请求只能排队等待,严重的会直接返回502或者504。建议在负载高的时段查看nginx -s reload前后日志中的upstream响应时间,如果耗时集中在后端等待阶段,就要考虑调整PHP-FPM的request_terminate_timeout,并适当调大进程池上限。同时留意后端服务调用外部接口时的超时设置,比如连接外部支付网关或短信平台时,connect_timeout设为3秒、read_timeout设为5秒是比较合理的起始值,不能无限等待导致请求积压。
使用CDN或者负载均衡时,需要确认回源策略是否配置正确。有些场景下,某一台应用节点已经挂掉,但负载均衡的健康检查机制没触发自动摘除,导致三成左右的请求被转发到坏节点上。检查一下负载均衡控制台中的后端服务器健康状态,如有异常节点及时下线,同时检查健康检查的探测路径是否指向一个稳定返回200的URL(比如 /healthz),避免用根路径做探测,因为根路径可能涉及过多动态逻辑,导致误判。
应用进程正常、请求也能到达后端,但接口返回非常慢,这时候要把排查重心放到数据库和缓存的读写性能上。数据库慢查询、连接数打满或者表锁竞争都可能造成整个应用卡死。
打开数据库的慢查询日志开关(MySQL中设置slow_query_log=ON, 并将long_query_time设为1秒),运行一段时间后再回看日志,找出响应时间最长的几条SQL语句。对每条慢SQL执行EXPLAIN查看执行计划,重点观察type列是否出现ALL(全表扫描),以及rows列是否远大于实际返回行数。一个常见场景是某个订单查询字段没有建索引,数据量达到几十万行后查询耗时从几十毫秒飙升到几秒,补上普通索引后通常能消除90%以上的查询延迟。
数据库连接池设置过小会导致应用频繁等待连接释放。检查连接池配置中的最大连接数(例如HikariCP的maximum-pool-size默认是10,高并发场景下建议调到30-50),并观察数据库端的show processlist,看看是否存在大量Sleep状态的闲置连接。同时检查Redis等缓存服务的命中率,如果接口设计上大量绕过了缓存直接查询数据库,即便数据库本身没有故障,也会因压力过大而变慢,此时应当调整缓存策略,把热点数据优先放入缓存并设置合理的过期时间。
ping通只代表服务器主机在网络层面是可达的,说明ICMP协议通畅,但Web服务可能没有启动,或者防火墙把80/443端口拦截了。优先用curl -I 域名查看HTTP响应码,再通过telnet 域名 443测试端口连通性,逐个排除Web服务状态和防火墙规则的问题。
这种地域性差异通常与CDN节点覆盖或不合理的DNS解析有关。可能部分地区的用户被解析到了距离较远的节点,或者该区域边缘节点缓存了过期数据。建议检查CDN服务商的分区域解析策略,并刷新全网缓存。如果没有使用CDN,也要确认不同运营商的线路是否有互联互通的瓶颈。
隐蔽的瞬时故障往往与慢SQL、垃圾回收暂停或者锁等待有关。建议开启慢查询日志观察是否有周期性出现的慢语句,同时查看应用日志中是否存在数据库连接获取超时的报错。另外,Java应用里的Full GC停顿或PHP-FPM的进程回收也可能造成偶发超时,需要结合监控报表把故障时间点和日志对应起来分析,而不是只看实时资源数据。
网站访问异常并不是无迹可寻的玄学问题,只要按网络链路、服务器资源、应用服务、数据存储这个顺序逐层排查,大部分故障都能在半小时内定位到方向。平时建议做好三项准备工作:一是为日志加上时间和响应耗时字段,便于事后回溯;二是配置基础的CPU、内存、磁盘和端口可用性监控;三是定期巡检DNS解析和CDN回源配置。当真正出问题时,手头有数据和路径,就不会手足无措。