1、前言
昨天總結了一下Linux下網路程式設計“驚群”現象, 給出Nginx處理驚群的方法, 使用互斥鎖。 為例發揮多核的優勢, 目前常見的網路程式設計模型就是多進程或多執行緒, 根據accpet的位置, 分為如下場景:
(1)單進程或執行緒創建socket, 並進行listen和accept, 接收到連接後創建進程和執行緒連接
(2)單進程或執行緒創建socket, 並進行listen, 預先創建好多個工作進程或執行緒accept在同一個伺服器通訊端、
這兩種模型解充分發揮了多核CPU的優勢,
Linux kernel 3.9帶來了SO_REUSEPORT特性, 可以解決以上大部分問題。
2、SO_REUSEPORT解決了什麼問題
SO_REUSEPORT支援多個進程或者執行緒綁定到同一埠, 提高伺服器程式的性能, 解決的問題:
允許多個通訊端 bind/listen 同一個TCP/UDP埠 每一個執行緒擁有自己的伺服器通訊端在伺服器通訊端上沒有了鎖的競爭內核層面實現負載均衡安全層面, 監聽同一個埠的通訊端只能位於同一個用戶下面其核心的實現主要有三點:
擴展 socket option, 增加 SO_REUSEPORT 選項,有了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