惊群问题及解决

1.什么是惊群?

当多个进程/线程同时等待同一个socket的事件,当事件发生时,多个进程/线程同时被唤醒,但只有一个进程/线程响应处理该事件,其他被唤醒的进程/线程重新休眠,这种情况称为惊群。

由于唤醒进程需要内核重新调度,所以那些没有响应处理事件的进程也被唤醒就意味着性能浪费,所以需要采取措施避免惊群发生。

需要说明的是,对于accept()函数,Linux2.6已经从内核层面解决了惊群问题,做法是当连接来到后,只唤醒等待队列中的第一个进程或线程。

2.什么情况下还会有这个问题?

当使用select,poll,epoll时,仍然会有惊群问题。

特别需要注意的是,即便是2.6以后的linux,epoll_wait在某些场景下不会出现惊群问题,但其仍旧有很大可能会在另外的场景中出现惊群问题。

例如,当epoll_wait之后又sleep的情况,因为信号将唤醒sleep,不再是内核唤醒等待队列中的第一个进程。

3.如何解决?

(1)在accept之前加锁,像Nginx那样;
lock;
accept();
unlock;

(2)在linux kernel 3.9之后利用SO_REUSEPORT,将socket属性加多一个SO_REUSEPORT
fcntl(serverFd,F_SETFL,flags | O_NONBLOCK |SO_REUSEPORT)

你可能感兴趣的:(惊群问题及解决)