您的位置:首頁>正文

Linux 最新SO_REUSEPORT特性

1、前言

昨天總結了一下Linux下網路程式設計“驚群”現象, 給出Nginx處理驚群的方法, 使用互斥鎖。 為例發揮多核的優勢, 目前常見的網路程式設計模型就是多進程或多執行緒, 根據accpet的位置, 分為如下場景:

(1)單進程或執行緒創建socket, 並進行listen和accept, 接收到連接後創建進程和執行緒連接

(2)單進程或執行緒創建socket, 並進行listen, 預先創建好多個工作進程或執行緒accept在同一個伺服器通訊端、

這兩種模型解充分發揮了多核CPU的優勢,

雖然可以做到執行緒和CPU核綁定, 但都會存在:

單一listener工作進程胡執行緒在高速的連接接入處理時會成為瓶頸多個執行緒之間競爭獲取服務通訊端緩存行跳躍很難做到CPU之間的負載均衡隨著核數的擴展, 性能並沒有隨著提升

Linux kernel 3.9帶來了SO_REUSEPORT特性, 可以解決以上大部分問題。

2、SO_REUSEPORT解決了什麼問題

SO_REUSEPORT支援多個進程或者執行緒綁定到同一埠, 提高伺服器程式的性能, 解決的問題:

允許多個通訊端 bind/listen 同一個TCP/UDP埠 每一個執行緒擁有自己的伺服器通訊端在伺服器通訊端上沒有了鎖的競爭內核層面實現負載均衡安全層面, 監聽同一個埠的通訊端只能位於同一個用戶下面

其核心的實現主要有三點:

擴展 socket option, 增加 SO_REUSEPORT 選項,
用來設置 reuseport。 修改 bind 系統調用實現, 以便支援可以綁定到相同的 IP 和埠修改處理新建連接的實現, 查找 listener 的時候, 能夠支持在監聽相同 IP 和埠的多個 sock 之間均衡選擇。

有了SO_RESUEPORT後, 每個進程可以自己創建socket、bind、listen、accept相同的位址和埠, 各自是獨立平等的。 讓多進程監聽同一個埠, 各個進程中accept socket fd不一樣, 有新連接建立時, 內核只會喚醒一個進程來accept, 並且保證喚醒的均衡性。

3、測試代碼

1 include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 14 #define IP "127.0.0.1" 15 #define PORT 8888 16 #define WORKER 4 17 #define MAXLINE 4096 18 19 int worker(int i) 20 { 21 struct sockaddr_in address; 22 bzero(&address, sizeof(address)); 23 address.sin_family = AF_INET; 24 inet_pton( AF_INET, IP, &address.sin_addr); 25 address.sin_port = htons(PORT); 26 27 int listenfd = socket(PF_INET, SOCK_STREAM, 0); 28 assert(listenfd >= 0); 29 30 int val =1; 31 /*set SO_REUSEPORT*/ 32 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val))

我的測試機器內核版本為:

測試結果如下所示:

從結果可以看出, 四個進程監聽相同的IP和port。

4、參考資料

http://lists.dragonflybsd.org/pipermail/users/2013-July/053632.html

http://www.blogjava.net/yongboy/archive/2015/02/12/422893.html

http://m.blog.chinaunix.net/uid-10167808-id-3807060.html

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示