1. 端口与进程基础

做运维这些年,我碰到过太多跟端口相关的故障了。服务起不来、连不上数据库、负载均衡报错……十有八九都能追溯到端口问题上。所以咱们这门课,就从最基础的东西讲起。

端口到底是什么?说白了,它就是计算机跟外界通信的「门牌号」。一台服务器上跑着几十上百个服务,数据包来了,系统得知道该交给谁处理。端口号就是用来做这个区分的。

一句话总结:IP 地址找到机器,端口号找到机器上的进程。

端口号范围:0-65535

端口号是一个 16 位的整数,所以范围是 0 到 65535。这个范围被分成了三段,每段的用途不一样。

范围 分类 说明 常见例子
0 - 1023 知名端口(Well-Known Ports) 系统保留,通常需要 root 权限才能绑定 HTTP(80), HTTPS(443), SSH(22), MySQL(3306)
1024 - 49151 注册端口(Registered Ports) 用户进程或应用程序使用,IANA 可注册 Tomcat(8080), Jenkins(8080), MongoDB(27017)
49152 - 65535 动态/私有端口(Dynamic/Private Ports) 临时端口,客户端发起连接时自动分配 浏览器访问网站时的临时端口

嗯,这里要注意一个坑。0 端口在 Linux 系统里是保留的,你不能直接用它。我曾经有个同事在配置 Nginx 时写了 listen 0;,结果服务一直起不来,查了半天才发现是端口号写错了。

我的习惯:生产环境里,自定义服务尽量用 1024 以上的端口。如果非要用知名端口,记得用 root 启动或者配置 capabilities。不然服务会报「Permission denied」。

知名端口 vs 动态端口

知名端口是固定的,比如 SSH 就是 22,HTTP 就是 80。这些端口在 /etc/services 文件里都有记录。你可以用 grep 80 /etc/services 看看。

动态端口就不一样了。你想想看,当你用浏览器访问一个网站时,你的机器需要开一个端口来接收返回的数据。这个端口是系统临时分配的,用完就释放。范围就是 49152-65535。

为什么会这样设计?因为客户端不需要固定的端口号,它只需要一个临时的通信通道。而服务端必须用固定的端口,否则客户端就找不到它。

我曾经踩过的坑:有一次线上服务突然变慢,排查发现是动态端口用完了。系统默认的 net.ipv4.ip_local_port_range 是 32768-60999,但并发连接数太大,端口被占满了。后来调大了范围才解决。

TCP 端口 vs UDP 端口

端口本身只是个数字,它跟协议是绑定的。TCP 和 UDP 的端口是独立的,也就是说 TCP 80 和 UDP 80 可以同时存在,互不影响。

特性 TCP UDP
连接方式 面向连接,三次握手 无连接,直接发数据
可靠性 可靠传输,有重传机制 不可靠,不保证送达
应用场景 Web、数据库、邮件 DNS、视频流、游戏
端口占用 一个端口一个连接 一个端口多个来源

我个人习惯用 ss -tlnp 看 TCP 端口,用 ss -ulnp 看 UDP 端口。这两个命令比 netstat 快很多,尤其是在高并发服务器上。

核心区别:TCP 端口是「一对一」的,一个连接独占一个端口。UDP 端口是「一对多」的,多个客户端可以同时往同一个 UDP 端口发数据。

进程与端口的关系

端口本身不干活,干活的是进程。一个进程可以绑定多个端口,但一个端口只能被一个进程绑定(除非用了 SO_REUSEPORT)。

你想想看,当你启动一个 Web 服务器时,它会在 80 端口上监听。系统内核收到发往 80 端口的数据包,就会把它交给这个进程。这就是端口和进程的关系——端口是入口,进程是处理者。

我记得有一次排查问题,发现 8080 端口被占用了,但不知道是谁占的。用 lsof -i :8080 一看,是个残留的 Java 进程。杀掉之后服务就正常了。这种场景在运维工作中太常见了。

排查命令速查:

  • ss -tlnp — 查看所有 TCP 监听端口及对应进程
  • ss -ulnp — 查看所有 UDP 监听端口及对应进程
  • lsof -i :端口号 — 查看指定端口被哪个进程占用
  • fuser 端口号/tcp — 快速找到占用端口的进程 PID

本章知识体系

下面这张图把端口、协议、进程的关系串起来了。建议你多看几遍,后面排查问题时脑子里能有个清晰的脉络。

端口与进程关系图 网络数据包(IP + 端口号) TCP 端口(可靠连接) UDP 端口(无连接) 知名端口 (0-1023) 注册端口 (1024-49151) 动态端口 (49152-65535) 临时端口(客户端) 进程(PID) — 实际处理数据的程序 Nginx / MySQL / Java / Python ... 一个端口只能被一个进程绑定,一个进程可以绑定多个端口 排查命令:ss -tlnp | lsof -i :端口 | fuser 端口/tcp

这张图从左到右看:数据包到达服务器后,先根据协议类型(TCP/UDP)分流,然后匹配端口号,最后交给对应的进程处理。整个链路清晰明了。

记住这个核心逻辑:端口是进程在网络上的「门牌号」。没有端口,进程就无法被外界访问。没有进程,端口就是个空号。