计算机网络学习指南计算机网络学习指南
首页
基础教程
进阶内容
实战案例
编程指南
首页
基础教程
进阶内容
实战案例
编程指南
  • 实战案例

    • 💼 实战案例
    • 🎯 学习目标
    • 🚀 学习路线
    • 📊 章节概览
  • 💡 学习建议
  • 🎓 学完之后
  • 第1章 - 前端开发的网络应用
  • 第2章 - 后端开发的网络应用
  • 第3章 - 运维与 DevOps
  • 第4章 - 测试与网络调试
  • 第5章 - 网络故障排查

第5章 - 网络问题排查

嗨,所有开发者们!

在实际工作中,你一定遇到过各种网络问题:接口调不通、网站打不开、请求超时、跨域报错……这些问题看起来很神秘,但只要掌握正确的排查方法,就能快速定位问题。

这一章,我会总结最常见的网络问题和解决方法,让你成为网络问题排查高手!

🔍 网络不通问题

问题现象

  • ping 不通服务器
  • 浏览器无法打开网站
  • 接口请求失败
  • SSH 连不上服务器

排查步骤

# 步骤1: 检查本地网络
ping 127.0.0.1
# 如果失败,说明本机网络协议栈有问题

# 步骤2: 检查网卡状态
ip link show
ifconfig
# 查看网卡是否 UP
# 如果是 DOWN,执行: sudo ip link set eth0 up

# 步骤3: 检查IP配置
ip addr show
# 确认是否获取到IP地址
# 如果没有,检查DHCP或静态IP配置

# 步骤4: 检查网关
ip route show
route -n
# 确认是否有默认网关
# 如果没有,添加: sudo ip route add default via 192.168.1.1

# 步骤5: 测试网关连通性
ping $(ip route | grep default | awk '{print $3}')
# 如果失败,检查物理连接或网关配置

# 步骤6: 测试公网连通性
ping 8.8.8.8
# 如果失败,可能是网关、防火墙或ISP问题

# 步骤7: 测试DNS解析
ping baidu.com
nslookup baidu.com
# 如果IP可以ping通但域名不行,是DNS问题

# 步骤8: 追踪路由
traceroute 8.8.8.8
tracepath baidu.com
# 查看在哪个路由节点丢包

# 步骤9: 检查防火墙
sudo iptables -L -n -v
sudo ufw status
# 查看是否被防火墙阻挡

# 步骤10: 检查端口状态
sudo netstat -tunlp | grep :80
sudo ss -tunlp | grep :80
# 确认服务是否在监听

常见原因和解决方案

原因现象解决方案
网线未连接网卡状态DOWN检查物理连接,重启网卡
IP配置错误没有IP地址重新配置IP或DHCP
网关配置错误无法访问外网正确配置默认网关
DNS问题域名无法解析修改DNS服务器
防火墙阻挡特定端口不通调整防火墙规则
路由问题部分网站不可访问检查路由表,联系网络管理员

🔍 DNS 解析问题

问题现象

  • 域名无法解析
  • 解析速度慢
  • 解析到错误的IP

排查步骤

# 1. 检查DNS配置
cat /etc/resolv.conf
# 确认nameserver配置是否正确

# 2. 测试DNS解析
nslookup baidu.com
dig baidu.com
host baidu.com

# 3. 指定DNS服务器测试
nslookup baidu.com 8.8.8.8
dig @8.8.8.8 baidu.com
# 对比不同DNS服务器的解析结果

# 4. 查看DNS缓存
sudo systemd-resolve --statistics
# Ubuntu/Debian

# 5. 清除DNS缓存
sudo systemd-resolve --flush-caches  # Ubuntu/Debian
sudo killall -HUP mDNSResponder      # macOS
ipconfig /flushdns                   # Windows

# 6. 检查hosts文件
cat /etc/hosts
# 查看是否有错误的静态解析

# 7. 测试DNS服务器连通性
ping 8.8.8.8
telnet 8.8.8.8 53
nc -zv 8.8.8.8 53

常用DNS服务器

# 国内DNS
114.114.114.114  # 114 DNS
223.5.5.5        # 阿里 DNS
119.29.29.29     # DNSPod

# 国外DNS
8.8.8.8          # Google DNS
8.8.4.4          # Google DNS
1.1.1.1          # Cloudflare DNS
1.0.0.1          # Cloudflare DNS

解决方案

# 1. 修改DNS服务器
sudo nano /etc/resolv.conf
# 添加:
nameserver 8.8.8.8
nameserver 114.114.114.114

# 2. Ubuntu/Debian 永久修改
sudo nano /etc/systemd/resolved.conf
# 修改:
DNS=8.8.8.8 114.114.114.114
sudo systemctl restart systemd-resolved

# 3. CentOS/RHEL
sudo nano /etc/sysconfig/network-scripts/ifcfg-eth0
# 添加:
DNS1=8.8.8.8
DNS2=114.114.114.114
sudo systemctl restart network

⏱️ 接口超时问题

问题现象

  • 请求超时
  • 响应很慢
  • 间歇性超时

排查步骤

# 1. 测试网络延迟
ping api.example.com
# 查看平均延迟时间

# 2. 测试连接时间
time curl -I https://api.example.com
# 查看总耗时

# 3. 详细请求耗时分析
curl -w "@curl-format.txt" -o /dev/null -s https://api.example.com

# curl-format.txt 内容:
time_namelookup:  %{time_namelookup}s\n
time_connect:     %{time_connect}s\n
time_appconnect:  %{time_appconnect}s\n
time_pretransfer: %{time_pretransfer}s\n
time_redirect:    %{time_redirect}s\n
time_starttransfer: %{time_starttransfer}s\n
time_total:       %{time_total}s\n
# 4. 检查服务器负载
top
htop
uptime  # 查看负载均值

# 5. 检查数据库连接
# MySQL
SHOW PROCESSLIST;
SHOW STATUS LIKE 'Threads%';

# 6. 检查日志
tail -f /var/log/nginx/error.log
tail -f /var/log/application.log

常见原因

// 1. 网络延迟高
// 解决:
// - 使用CDN加速
// - 选择距离更近的服务器
// - 优化网络路由

// 2. 服务器处理慢
// 解决:
// - 优化代码逻辑
// - 添加缓存
// - 增加服务器资源

// 3. 数据库查询慢
// 解决:
// - 添加索引
// - 优化SQL语句
// - 使用查询缓存

// 4. 连接池耗尽
// 解决:
// - 增大连接池
// - 修复连接泄漏
// - 设置连接超时

// 5. 第三方服务慢
// 解决:
// - 设置超时时间
// - 使用异步请求
// - 添加重试机制

优化建议

// 设置合理的超时时间
const axios = require('axios');

const api = axios.create({
  timeout: 5000,  // 5秒超时
  retry: 3,       // 重试3次
  retryDelay: 1000 // 重试间隔1秒
});

// 添加超时重试
api.interceptors.response.use(null, async (error) => {
  const config = error.config;
  
  if (!config || !config.retry) {
    return Promise.reject(error);
  }
  
  config.__retryCount = config.__retryCount || 0;
  
  if (config.__retryCount >= config.retry) {
    return Promise.reject(error);
  }
  
  config.__retryCount += 1;
  
  await new Promise(resolve => setTimeout(resolve, config.retryDelay));
  
  return api(config);
});

❌ 跨域问题 (CORS)

问题现象

// 控制台错误:
Access to XMLHttpRequest at 'https://api.example.com/users' 
from origin 'https://www.example.com' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

排查步骤

# 1. 检查是否跨域
# 当前页面: https://www.example.com
# 请求接口: https://api.example.com
# 协议/域名/端口不同即为跨域

# 2. 检查响应头
curl -I https://api.example.com/users
# 查看是否有 Access-Control-Allow-Origin 头

# 3. 测试 OPTIONS 请求
curl -X OPTIONS https://api.example.com/users \
  -H "Origin: https://www.example.com" \
  -H "Access-Control-Request-Method: POST" \
  -v
# 查看预检请求是否成功

后端解决方案

// Express.js
const cors = require('cors');

// 方法1: 允许所有源 (仅开发环境)
app.use(cors());

// 方法2: 指定允许的源 (推荐)
app.use(cors({
  origin: ['https://www.example.com', 'https://app.example.com'],
  credentials: true,  // 允许携带Cookie
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  maxAge: 86400  // 预检结果缓存24小时
}));

// 方法3: 手动设置响应头
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Credentials', 'true');
  res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');
  
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  
  next();
});
# Nginx 配置
server {
    listen 80;
    server_name api.example.com;
    
    location / {
        # 允许所有源 (仅开发环境)
        add_header Access-Control-Allow-Origin *;
        
        # 指定允许的源 (推荐)
        add_header Access-Control-Allow-Origin "https://www.example.com";
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
        add_header Access-Control-Allow-Headers "Content-Type, Authorization";
        add_header Access-Control-Allow-Credentials "true";
        add_header Access-Control-Max-Age 86400;
        
        # 处理 OPTIONS 请求
        if ($request_method = OPTIONS) {
            return 204;
        }
        
        proxy_pass http://localhost:3000;
    }
}

前端解决方案

// 方法1: 使用代理 (开发环境)
// vite.config.js
export default {
  server: {
    proxy: {
      '/api': {
        target: 'https://api.example.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
}

// 使用
fetch('/api/users')  // 实际请求 https://api.example.com/users

// 方法2: JSONP (仅支持GET)
function jsonp(url, callback) {
  const callbackName = 'jsonp_' + Date.now();
  window[callbackName] = callback;
  
  const script = document.createElement('script');
  script.src = `${url}?callback=${callbackName}`;
  document.body.appendChild(script);
}

🔒 HTTPS 证书问题

问题现象

  • 浏览器提示“您的连接不是私密连接”
  • SSL 证书过期
  • 证书域名不匹配
  • 中间证书缺失

排查步骤

# 1. 检查证书信息
openssl s_client -connect example.com:443 -servername example.com
# 查看证书详情

# 2. 检查证书有效期
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

# 3. 检查证书链
openssl s_client -connect example.com:443 -showcerts

# 4. 验证证书
openssl verify -CAfile ca-bundle.crt certificate.crt

# 5. 在线检测工具
# https://www.ssllabs.com/ssltest/

解决方案

# 1. 使用 Let's Encrypt 免费证书

# 安装 certbot
sudo apt install certbot python3-certbot-nginx

# 申请证书
sudo certbot --nginx -d example.com -d www.example.com

# 自动续期
sudo certbot renew --dry-run

# 添加到 crontab
0 3 * * * certbot renew --quiet

# 2. 配置 Nginx HTTPS
server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
}

# 3. HTTP 自动跳转 HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

🐌 网络慢的原因分析

问题现象

  • 网页加载慢
  • 接口请求慢
  • 文件下载慢

排查步骤

# 1. 测试网络速度
# 下载 speedtest-cli
sudo apt install speedtest-cli
speedtest-cli

# 2. 测试带宽
wget http://speedtest.tele2.net/100MB.zip
# 查看下载速度

# 3. 检查网络延迟
ping -c 100 api.example.com
# 查看平均延迟和丢包率

# 4. 检查MTU设置
ip link show
# MTU 通常为 1500

# 5. 检查网络负载
iftop -i eth0
nload eth0

# 6. 检查连接数
netstat -an | grep ESTABLISHED | wc -l
ss -s

# 7. 检查服务器负载
top
htop
uptime

常见原因

// 1. 网络带宽不足
// 解决:
// - 升级带宽
// - 使用CDN
// - 压缩资源

// 2. DNS解析慢
// 解决:
// - 更换DNS服务器
// - 使用DNS缓存

// 3. 资源文件过大
// 解决:
// - 压缩图片
// - 使用WebP格式
// - 代码分割加载

// 4. 请求数量过多
// 解决:
// - 合并请求
// - 使用精灵图
// - 懒加载

// 5. 服务器处理慢
// 解决:
// - 优化代码
// - 添加缓存
// - 水平扩展

// 6. 数据库查询慢
// 解决:
// - 添加索引
// - 优化SQL
// - 使用读写分离

🛠️ 常用诊断命令

网络连通性

# ping - 测试网络连通性
ping -c 4 baidu.com

# traceroute - 追踪路由
traceroute baidu.com
tracepath baidu.com

# mtr - 综合ping和traceroute
mtr baidu.com

# telnet - 测试端口连通性
telnet 192.168.1.100 80

# nc (netcat) - 网络工具
nc -zv 192.168.1.100 80
nc -l 8888  # 监听端口

DNS诊断

# nslookup - DNS查询
nslookup baidu.com
nslookup baidu.com 8.8.8.8

# dig - DNS详细信息
dig baidu.com
dig @8.8.8.8 baidu.com
dig +trace baidu.com  # 跟踪DNS解析过程

# host - 简单DNS查询
host baidu.com

网络状态

# netstat - 网络连接状态
netstat -tunlp          # 查看所有监听端口
netstat -an | grep EST  # 查看已建立连接
netstat -s              # 网络统计信息

# ss - 更快的netstat
ss -tunlp
ss -s                   # 统计信息

# lsof - 查看端口占用
sudo lsof -i :80
sudo lsof -i tcp

抓包分析

# tcpdump - 抓包工具
sudo tcpdump -i eth0
sudo tcpdump -i eth0 port 80
sudo tcpdump -i eth0 host 192.168.1.100
sudo tcpdump -i eth0 -w capture.pcap

# tshark - Wireshark命令行版
tshark -i eth0
tshark -r capture.pcap

HTTP请求

# curl - HTTP客户端
curl -I https://baidu.com          # 查看响应头
curl -v https://baidu.com          # 详细信息
curl -X POST -d '{"key":"value"}' https://api.example.com

# wget - 下载工具
wget https://example.com/file.zip
wget -O output.html https://example.com

# ab - 性能测试
ab -n 1000 -c 10 https://example.com/

📝 快速排查流程图

graph TB
    A[网络问题] --> B{能启ping通吗?}
    B -->|No| C[检查网络配置]
    C --> C1[检查网卡状态]
    C --> C2[检查IP配置]
    C --> C3[检查网关配置]
    
    B -->|Yes| D{IP可以但域名不可以?}
    D -->|Yes| E[DNS问题]
    E --> E1[检查DNS配置]
    E --> E2[清除DNS缓存]
    E --> E3[更换DNS服务器]
    
    D -->|No| F{特定端口不通?}
    F -->|Yes| G[防火墙问题]
    G --> G1[检查防火墙规则]
    G --> G2[检查服务状态]
    
    F -->|No| H{请求超时?}
    H -->|Yes| I[性能问题]
    I --> I1[检查服务器负载]
    I --> I2[检查数据库性能]
    I --> I3[优化代码]
    
    H -->|No| J[其他问题]
    J --> J1[查看错误日志]
    J --> J2[抓包分析]

💡 最佳实践

1. 日常检查清单

#!/bin/bash
# daily-check.sh - 每日网络检查

echo "=== 日常网络检查 ==="
echo "时间: $(date)"
echo ""

# 1. 网络连通性
echo "1. 网络连通性"
ping -c 4 8.8.8.8 > /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo "   ✅ 网络连通性正常"
else
    echo "   ❌ 网络连接失败"
fi

# 2. DNS解析
echo "2. DNS解析"
nslookup baidu.com > /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo "   ✅ DNS解析正常"
else
    echo "   ❌ DNS解析失败"
fi

# 3. 关键服务
echo "3. 关键服务"
for service in nginx mysql; do
    systemctl is-active --quiet $service
    if [ $? -eq 0 ]; then
        echo "   ✅ $service 运行正常"
    else
        echo "   ❌ $service 未运行"
    fi
done

# 4. 端口监听
echo "4. 端口监听"
for port in 80 443 3306; do
    netstat -tunl | grep ":$port" > /dev/null
    if [ $? -eq 0 ]; then
        echo "   ✅ 端口 $port 正在监听"
    else
        echo "   ❌ 端口 $port 未监听"
    fi
done

# 5. SSL证书
echo "5. SSL证书检查"
CERT_FILE="/etc/letsencrypt/live/example.com/cert.pem"
if [ -f "$CERT_FILE" ]; then
    EXPIRY=$(openssl x509 -enddate -noout -in "$CERT_FILE" | cut -d= -f2)
    EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
    NOW_EPOCH=$(date +%s)
    DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
    
    if [ $DAYS_LEFT -lt 30 ]; then
        echo "   ⚠️  证书将在 $DAYS_LEFT 天后过期"
    else
        echo "   ✅ 证书有效期还有 $DAYS_LEFT 天"
    fi
fi

echo ""
echo "=== 检查完成 ==="

2. 问题记录

# 网络问题记录表

| 日期 | 问题描述 | 原因 | 解决方案 | 处理人 |
|------|----------|------|----------|--------|
| 2024-01-15 | 接口超时 | 数据库查询慢 | 添加索引 | 张三 |
| 2024-01-10 | 跨域错误 | 未CORS配置 | 后端添加CORS | 李四 |
| 2024-01-05 | DNS解析失败 | DNS服务器故障 | 更换DNS | 王五 |

3. 建立监控告警

// monitor.js - 简单的接口监控
const axios = require('axios');

const endpoints = [
  { name: '主页', url: 'https://example.com' },
  { name: '用户API', url: 'https://api.example.com/users' },
  { name: '订单API', url: 'https://api.example.com/orders' }
];

async function checkEndpoint(endpoint) {
  try {
    const startTime = Date.now();
    const response = await axios.get(endpoint.url, { timeout: 5000 });
    const duration = Date.now() - startTime;
    
    console.log(`✅ ${endpoint.name}: ${response.status} (${duration}ms)`);
    
    if (duration > 1000) {
      console.warn(`⚠️  ${endpoint.name} 响应较慢: ${duration}ms`);
    }
  } catch (error) {
    console.error(`❌ ${endpoint.name}: ${error.message}`);
    // 发送告警通知
  }
}

async function monitor() {
  console.log(`[${new Date().toISOString()}] 开始监控...`);
  
  for (const endpoint of endpoints) {
    await checkEndpoint(endpoint);
  }
  
  console.log('');
}

// 每分钟检查一次
setInterval(monitor, 60000);
monitor();

📝 小结

这一章我们学习了:

✅ 网络不通排查:系统性排查网络连接问题
✅ DNS问题:DNS解析失败、解析慢的解决
✅ 接口超时:定位和优化超时问题
✅ 跨域问题:CORS配置和解决方案
✅ HTTPS证书:证书问题排查和配置
✅ 性能问题:网络慢的原因分析和优化
✅ 诊断工具:掌握常用网络诊断命令

🎉 恐喜你!

恐喜你完成了所有实战案例的学习!

现在你已经:

✅ 掌握了计算机网络的基础知识
✅ 理解了网络协议的工作原理
✅ 学会了在实际工作中应用网络知识
✅ 掌握了网络问题的排查方法

接下来建议你:

  1. 持续实践 - 在工作中应用所学知识
  2. 总结经验 - 记录遇到的问题和解决方法
  3. 深入学习 - 阅读相关技术书籍和文档
  4. 分享交流 - 和同事分享你的经验
  5. 关注动态 - 关注网络技术的最新发展

返回实战案例首页


由 编程指南 提供

最近更新: 2025/12/27 10:13
Contributors: 王长安
Prev
第4章 - 测试与网络调试