驚羣問題及解決

1.什麼是驚羣?

當多個進程/線程同時等待同一個socket的事件,當事件發生時,多個進程/線程同時被喚醒,但只有一個進程/線程響應處理該事件,其餘被喚醒的進程/線程從新休眠,這種狀況稱爲驚羣。linux

因爲喚醒進程須要內核從新調度,因此那些沒有響應處理事件的進程也被喚醒就意味着性能浪費,因此須要採起措施避免驚羣發生。socket

須要說明的是,對於accept()函數,Linux2.6已經從內核層面解決了驚羣問題,作法是當鏈接來到後,只喚醒等待隊列中的第一個進程或線程。函數

2.什麼狀況下還會有這個問題?

當使用select,poll,epoll時,仍然會有驚羣問題。性能

特別須要注意的是,即使是2.6之後的linux,epoll_wait在某些場景下不會出現驚羣問題,但其仍舊有很大可能會在另外的場景中出現驚羣問題。線程

例如,當epoll_wait以後又sleep的狀況,由於信號將喚醒sleep,再也不是內核喚醒等待隊列中的第一個進程。server

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)進程

相關文章
相關標籤/搜索