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
本章知识体系
下面这张图把端口、协议、进程的关系串起来了。建议你多看几遍,后面排查问题时脑子里能有个清晰的脉络。
这张图从左到右看:数据包到达服务器后,先根据协议类型(TCP/UDP)分流,然后匹配端口号,最后交给对应的进程处理。整个链路清晰明了。
记住这个核心逻辑:端口是进程在网络上的「门牌号」。没有端口,进程就无法被外界访问。没有进程,端口就是个空号。