1. 端口复用概述
端口复用,说白了就是让多个网络连接共享同一个端口。你可能会问:端口不是一对一绑定的吗?嗯,传统模型确实是——一个端口对应一个服务。但现实场景中,连接数一上来,端口就成了稀缺资源。
我记得刚接手第一个高并发项目时,服务器端口不够用,业务直接报错。那时候我才意识到,端口复用不是锦上添花,而是刚需。
什么是端口复用
端口复用允许不同进程或线程,绑定到同一个 IP 地址和端口号。内核在收到数据包时,根据复用策略把数据分发给对应的 socket。
常见的实现方式有两种:
- SO_REUSEADDR:允许重用 TIME_WAIT 状态的端口。我习惯在服务端 socket 创建后立刻设置这个选项。
- SO_REUSEPORT:允许多个进程/线程绑定到完全相同的 IP:端口,内核做负载均衡。这个在 Linux 3.9+ 才支持。
核心区别:SO_REUSEADDR 解决的是端口被占用的问题,SO_REUSEPORT 解决的是多进程共享端口的问题。两者经常搭配使用。
端口复用的应用场景
我总结了几类典型场景,你在实际项目中大概率会遇到:
| 场景 | 说明 | 复用方式 |
|---|---|---|
| 高并发 Web 服务 | Nginx、Apache 等多进程模型 | SO_REUSEPORT |
| 快速重启服务 | 旧进程未完全关闭,新进程立即启动 | SO_REUSEADDR |
| 透明代理/负载均衡 | 代理服务器复用源端口转发请求 | SO_REUSEADDR |
| 容器化部署 | 多个容器实例共享宿主机端口 | SO_REUSEPORT |
| 高性能网关 | Kong、Envoy 等网关的多 worker 模型 | SO_REUSEPORT |
举个例子。我曾经帮一个电商团队调优,他们的订单服务每秒钟要处理上万请求。单进程模型扛不住,改成多进程 + SO_REUSEPORT 后,吞吐量直接翻了三倍。你想想看,端口复用在这里起的作用就是让多个 worker 同时干活,互不干扰。
端口复用的核心价值
端口复用的价值,我归纳为三点:
- 提高端口利用率:一个端口可以服务海量连接,避免端口耗尽。我记得有个极端案例,客户端短连接太多,TIME_WAIT 把端口池占满了,开了 SO_REUSEADDR 后问题立刻解决。
- 提升并发能力:多进程/多线程共享端口,充分利用多核 CPU。说白了就是让每个核都忙起来,而不是一个核累死,其他核闲着。
- 实现无缝重启:旧进程还在处理请求,新进程已经可以绑定同一端口。我曾经在凌晨做灰度发布,靠 SO_REUSEPORT 做到了零停机切换。
避坑指南:我曾经在旧版 Linux 内核上使用 SO_REUSEPORT,结果发现连接分配不均匀。后来查资料才知道,内核版本低于 4.5 时,SO_REUSEPORT 的负载均衡算法有缺陷。升级内核后问题消失。
下面这张图,帮你快速理解端口复用的核心逻辑:
注意:端口复用不是银弹。滥用 SO_REUSEPORT 可能导致连接分配不均,尤其是在短连接场景下。我建议你在开启前,先做好压测,观察每个 worker 的连接数分布。
总结一下。端口复用是高性能网络编程的基础技能。你不需要一开始就精通所有细节,但至少要知道:什么时候该用,用了能解决什么问题。后面的章节,我会带你深入每个复用选项的底层原理和调优参数。