SO_REUSEADDR
vs SO_REUSEPORT
BSD
SO_REUSEADDR
效果1:0.0.0.0:21
与127.0.0.1:21
可以同时绑定
效果2:
对于TCP连接,绑定到某个特定IP+port时,可以忽略其time_wait状态
注意:该选项只对调用bind()的新套接字有效,与正在占用地址的套接字是否使用了该选项无关。
SO_REUSEPORT
效果:允许多个套接字绑定到相同的IP+port
注意:必须前一个套接字也设置了该选项才行。
对于组播,这两个选项的作用是一样的。
Linux
Linux < 3.9
没有SO_REUSEPORT
选项。
注意:
- 如果有TCP套接字绑定了
0.0.0.0:21
并处于监听状态,就不能再绑定127.0.0.1:21
- reuseaddr与reuseport的作用相似,如果前一个套接字设置了
SO_REUSEADDR
,后面的套接字也设置这个选项就可以绑定相同的地址和端口
Linux >= 3.9
引入了SO_REUSEPORT
。
特殊效果:可实现负载均衡
注意:前后两个套接字所属进程必须有相同的有效UID。
Nginx惊群效应
惊群效应
父进程创建套接字,绑定并监听;所有子进程accept,然后epoll。此时新连接到来,所有子进程均被唤醒,造成不必要竞争,称为惊群效应。
解决方法
accept_mutex
所有子进程在accpet之前先取accept_mutex,成功取到锁的才会调用accept。实质上是把惊群推迟到空闲时间,在新连接到来时不发生惊群,提升新连接响应速度。
reuseport
Linux >= 3.9
父进程不创建套接字,每个子进程各自创建自己的,绑定到相同地址并监听。新连接到来时,内核将连接请求交付到某一个套接字上,从而避免了惊群。
EPOLLEXCLUSIVE
Linux >= 4.5 && nginx >= 1.11.3
epoll支持EPOLLEXCLUSIVE
选项,如果有多个进程监听同一个套接字,则epoll只唤醒其中一个进程,也从根源上避免了惊群。
参考资料
https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。