CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
DevOps 入门实战/课时/网络协议
RawBlame
课时目录12 节

DevOps 入门实战

  1. 01DevOps 入门
  2. 02操作系统
  3. 03Git 与 GitHub
  4. 04脚本语言
  5. 05网络协议
  6. 06Docker
  7. 07AWS
  8. 08Terraform
  9. 09Ansible
  10. 10GitHub Actions
  11. 11Nginx
  12. 12综合练习

网络协议

TCP/HTTP/DNS 概览。

25 分钟

网络协议

这一课你将能做到

  1. 说清楚一个 HTTP 请求从浏览器到 Nginx 再到 Spring Boot 的全链路过程
  2. 用 tcpdump、curl、ss 等命令抓包诊断网络问题
  3. 配置 HTTPS(TLS 证书)并理解握手过程,能把 HTTP 301 到 HTTPS

为什么要学

你的 Spring Boot 应用、MySQL、Redis、Nginx 跑在网络上,用户请求跨越公网、VPC、内网才能到达你的代码。网络不通?SSL 证书报错?连接超时?DNS 解析失败?不会抓包和看协议的 DevOps 等于蒙眼修车。

人话:网络协议是「两台电脑如何对话」的规则。HTTP 是浏览器和服务器之间的对话格式,TCP 是「保证对方一定收到」的快递单号机制,DNS 是把域名翻译成 IP 地址的电话簿。理解这些,排查「为什么连不上」才有方向。

先建立图像

一个完整的请求链路:

用户浏览器
    │  https://www.codeforge.com/api/users
    ▼
DNS 解析 → 8.8.8.8 / 114.114.114.114
    │  www.codeforge.com → 47.96.123.45
    ▼
公网 → 云服务器安全组(443 放行)→ 服务器 443 端口
    │  Nginx 监听 443,做 TLS 握手
    ▼
Nginx
    │  反向代理 → proxy_pass http://127.0.0.1:8080
    ▼
Spring Boot(8080)
    │  查缓存(Redis:6379)或查数据库(MySQL:3306)
    ▼
JSON 响应

TCP 三次握手(建立连接)与四次挥手(断开连接):

三次握手(为了确认双方收发都正常):
客户端 → SYN → 服务端
服务端 → SYN+ACK → 客户端
客户端 → ACK → 服务端

四次挥手(双方各自收拾干净再挂电话):
客户端 → FIN → 服务端
服务端 → ACK → 客户端
服务端 → FIN → 客户端
客户端 → ACK → 服务端

跟着做

步骤 1:在服务器上确认网络拓扑

# 本机 IP 和网卡
ip addr

# 路由表:包往哪走
ip route

# DNS 配置
cat /etc/resolv.conf

# 域名解析过程追踪
dig www.codeforge.com +trace

步骤 2:确认端口监听和连接状态

# 四连问
ss -tlnp                      # TCP 监听端口(LISTEN)
ss -tan state established     # 已建立连接
ss -s                         # 连接数统计
netstat -i                    # 网卡流量统计

连接状态的含义:

LISTEN       服务在等连接
ESTABLISHED  双方正在通信
TIME_WAIT    连接已断开,等最后确认(2MSL,约 60 秒)
CLOSE_WAIT   对方已关,我方还没关(通常是我方程序 bug)
SYN_SENT     正在发 SYN 等回应(可能连不上目标)

步骤 3:用 curl 模拟请求,调试 HTTP

# 基础 GET
curl -v https://api.codeforge.com/users?page=1

# -v 会打印完整握手和响应头,调试必备

# POST JSON
curl -X POST https://api.codeforge.com/users \
  -H "Content-Type: application/json" \
  -d '{"name":"alice"}' \
  -w "\nHTTP_CODE: %{http_code}\nTIME: %{time_total}s\n"

# 只看响应头和状态码(不下载 body)
curl -I -s -o /dev/null -w "%{http_code}" https://api.codeforge.com/health

步骤 4:抓包分析——tcpdump 实战

# 抓 80 端口的包,保存到文件(Wireshark 能打开分析)
sudo tcpdump -i any port 80 -w /tmp/http.pcap

# 实时看 443 端口的握手过程(不存文件)
sudo tcpdump -i any port 443 -nn -X | head -30

# 只抓某个 IP 到本机 8080 的包
sudo tcpdump host 1.2.3.4 and port 8080

抓到包后,用 Wireshark 打开 .pcap 文件,能看到 TCP 握手、TLS 握手、HTTP 请求/响应的完整过程。

步骤 5:配置 HTTPS(Let's Encrypt 免费证书)

# 安装 certbot(以 Ubuntu 为例)
sudo apt install certbot python3-certbot-nginx

# 一键申请并自动配置 Nginx
sudo certbot --nginx -d www.codeforge.com -d codeforge.com

# 测试自动续期(证书 90 天有效)
sudo certbot renew --dry-run

申请完后 Nginx 配置会变成这样:

server {
    listen 443 ssl;
    server_name www.codeforge.com;

    ssl_certificate     /etc/letsencrypt/live/www.codeforge.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.codeforge.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

server {
    listen 80;
    server_name www.codeforge.com;
    return 301 https://$server_name$request_uri;   # HTTP 强制跳转 HTTPS
}

讲清楚要点

  1. TCP 是可靠传输,UDP 是快速传输:Spring Boot 的 HTTP 走 TCP(数据不会丢),DNS 查询默认走 UDP(快,丢了重发一次就行)。
  2. 三次握手的本质:防止历史重复连接导致的混乱,同时让双方确认「自己发得出去,也收得到」。
  3. HTTPS = HTTP + TLS:TLS(旧称 SSL)在 TCP 连接之上做加密握手,交换对称密钥,之后所有 HTTP 数据都是密文。证书(Certificate)解决「你是不是真服务器」的信任问题。
  4. 301 vs 302:301 是永久重定向(浏览器会缓存,下次直接走新地址),302 是临时重定向。HTTP 跳转 HTTPS 用 301。
  5. 连接池是性能关键:Spring Boot 连接 MySQL、Redis,Nginx 连接后端,都有连接池。TCP 连接建立成本不低,频繁新建/断开会拖慢性能。ss -s 看到 TIME_WAIT 过多,通常是短连接风暴。

你可能会懵的地方

  • 为什么 TIME_WAIT 这么多? TCP 协议规定主动关闭方要等 2MSL(约 60 秒)才能彻底释放端口,防止最后的 ACK 丢失导致对方重发 FIN 没人收。高并发短连接场景(如爬虫)下会大量堆积,解决方案是改用连接池、或调内核参数 net.ipv4.tcp_tw_reuse。

  • 127.0.0.1、0.0.0.0、外网 IP 监听有什么区别? 127.0.0.1 只接受本机连接(MySQL 默认这样,安全);0.0.0.0 接受所有网卡上的连接(Nginx 和 Spring Boot 通常这样);外网 IP 明确绑定某张网卡。绑定错了就是「明明服务在跑,外面却连不上」的元凶。

  • 端口被占用了怎么办? ss -tlnp | grep 8080 找到占用的 PID → ps aux | grep <pid> 确认是谁 → 决定杀进程还是改端口。Java 进程常见:上次没正常退出,旧进程还在监听。

  • ping 能通但服务访问不了? ping 走 ICMP 协议,只证明网络层通;服务访问不了可能是:防火墙/安全组没放行端口、服务没监听、服务绑定了 127.0.0.1、Nginx 配错了 upstream。

  • 为什么证书配好了浏览器还报不安全? 常见原因:证书链不完整(缺少中间证书)、域名不匹配(证书是 *.example.com 但访问的是 sub.sub.example.com)、证书过期。用 openssl s_client -connect host:443 -servername host 检查。

错法对照

错法问题正解
MySQL 绑定 0.0.0.0 且安全组放行 3306数据库暴露公网,极危险绑定 127.0.0.1,或走内网/VPC
用 IP 而非域名访问服务换服务器要全改配置用域名 + DNS,换 IP 只改解析
HTTP 200 就认为服务健康可能返回的是错误页健康接口查业务状态,不只是 TCP 通
防火墙全放行等于没防火墙最小端口开放,用安全组精确控制
证书过期没续期全站 HTTPS 报错certbot 自动续期 + 监控告警

卡点急救

  1. curl 报错 Connection refused:目标端口没进程监听 → ss -tlnp | grep 端口 确认;或被防火墙拦 → 检查 iptables -L 和云安全组。
  2. curl 报错 SSL certificate problem:服务器证书链不完整、或自签证书不被信任。测试时加 -k 跳过验证(仅测试),生产环境必须配合法证书。
  3. 服务间歇性超时:ss -tan | grep CLOSE_WAIT | wc -l,如果几百个 CLOSE_WAIT,说明服务端代码没正确关闭连接(连接泄漏),Java 里常见于没关 InputStream/ResultSet。

面试常问

  • 输入 URL 到页面显示,发生了什么? 按顺序讲:DNS 解析(缓存→递归查询)→ TCP 三次握手 → TLS 握手(HTTPS)→ HTTP 请求 → Nginx 处理 → 反向代理到 Spring Boot → 业务逻辑 → 查 Redis/MySQL → 组装响应 → HTTP 响应 → 浏览器渲染。能讲到这个粒度,网络基础就过关了。

  • TCP 三次握手能不能改成两次? 不能。两次握手只能确认「客户端能发、服务端能收」,但无法确认「服务端能发、客户端能收」。另外,历史过期连接如果只有两次握手,会在服务端错误建立连接。

  • HTTPS 和 HTTP 的区别?TLS 握手过程? HTTPS 在 HTTP 之下加了 TLS 加密层。握手过程简版:①客户端发支持的加密套件和随机数;②服务端返回证书+随机数;③客户端验证书,生成预主密钥用公钥加密发给服务端;④双方用三个随机数算出会话密钥;⑤之后所有通信用对称加密。curl -v https://... 能看到部分握手细节。

自测三问

  1. ss -tlnp 里的 t、l、n、p 分别代表什么?输出中 0.0.0.0:80 和 127.0.0.1:3306 的安全含义有何不同?
  2. 你 curl 一个接口返回 502 Bad Gateway,下一步排查的三条命令是什么?
  3. 为什么生产环境必须把 HTTP 301 到 HTTPS,而不是让用户自己输入 https://?

小结一句话

网络协议是 DevOps 的「血管系统」:理解 DNS、TCP、HTTP、TLS 的请求链路,才能快速定位「连不上、慢、不安全」的问题。

延伸

  • 图解 HTTP(豆瓣链接)
  • 下一课:Docker——把你的应用和环境打包成一个可移植的集装箱。
加载本节练习…
← 上一课脚本语言下一课 →Docker