SO_REUSEPORT

int
evutil_make_listen_socket_reuseable_port(evutil_socket_t sock)
{
#if defined __linux__ && defined(SO_REUSEPORT)
    int one = 1;
    /* REUSEPORT on Linux 3.9+ means, "Multiple servers (processes or
     * threads) can bind to the same port if they each set the option. */
    return setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*) &one,
     (ev_socklen_t)sizeof(one));
#else
    return 0;
#endif
}


以前就在國外的論壇接觸過SO_REUSEPORT,這兩天朋友羣又在傳播nginx 1.9 reuseport多進程監聽參數。那咱們簡單說下SO_REUSEPORT的應用場景, 爲什麼會用他? 然而在講解SO_REUSEPORT之前,需要先說下我們常用的網絡模型。

文章寫得不太嚴謹, 請磚家拍磚,另外標註下原文地址,  http://xiaorui.cc/?p=2413


在多核時代,一般主流的web服務器都使用 SO_REUSEADDR模式。 以下是比較典型的多進程/多線程服務器模型。


首先需要單線程listen一個端口上,然後由多個工作進程/線程去accept()在同一個服務器套接字上。 


第一個性能瓶頸,單線程listener,在處理高速率海量連接時,一樣會成爲瓶頸

第二個性能瓶頸,多線程訪問server socket鎖競爭嚴重。

那麼怎麼解決? 這裏先別扯什麼分佈式調度,集羣xxx的 , 就拿單機來說問題。在Linux kernel 3.9帶來了SO_REUSEPORT特性,她可以解決上面(單進程listen,多工作進程accept() )的問題.


看圖說話,對比SO_REUSADDR的模型,我想你應該看懂SO_REUSEPORT是個什麼東西了。  SO_REUSEPORT是支持多個進程或者線程綁定到同一端口,提高服務器程序的吞吐性能,具體來說解決了下面的幾個問題:

允許多個套接字 bind()/listen() 同一個TCP/UDP端口
每一個線程擁有自己的服務器套接字
在服務器套接字上沒有了鎖的競爭,因爲每個進程一個服務器套接字
內核層面實現負載均衡
安全層面,監聽同一個端口的套接字只能位於同一個用戶下面

我這邊用python做了一個關於python SO_REUSEPORT服務端測試.   測試之前,已經要確定你的linux內核版本是3.9, 在mac下進行so_reuseport測試,貌似不會提示端口被綁定,但是後啓動的進程會阻塞.

file: reuseport.py

開始測試reuseport.py 

使用nc測試

有些文章說,在python下多進程綁定同一個端口,也就是有人常說的prefork,他其實也是單個進程去listen監聽端口,剩餘的worker去accept獲取用戶請求而已.  如果想用python實現真正的多進程綁定在多一個端口,那隻能是用so_reuseport模式 。 

其實用python開發支持SO_REUSEPORT的服務端有個大好處,不用寫多進程,多線程了..   算是一個偷懶的方法。 我自己覺得python離SO_REUSEPORT真實提高socket性能的應用場景比較的遠,就python這性能….倒是可以迅速的提高socket開發效率..      


另外標註下,SO_REUSEADDR和SO_REUSEPORT的區別:
SO_REUSEADDR提供如下四個功能:
    SO_REUSEADDR允許啓動一個監聽服務器並捆綁其衆所周知端口,即使以前建立的將此端口用做他們的本地端口的連接仍存在。這通常是重啓監聽服務器時出現,若不設置此選項,則bind時將出錯。
    SO_REUSEADDR允許在同一端口上啓動同一服務器的多個實例,只要每個實例捆綁一個不同的本地IP地址即可。對於TCP,我們根本不可能啓動捆綁相同IP地址和相同端口號的多個服務器。
    SO_REUSEADDR允許單個進程捆綁同一端口到多個套接口上,只要每個捆綁指定不同的本地IP地址即可。這一般不用於TCP服務器。
    SO_REUSEADDR允許完全重複的捆綁:當一個IP地址和端口綁定到某個套接口上時,還允許此IP地址和端口捆綁到另一個套接口上。一般來說,這個特性僅在支持多播的系統上纔有,而且只對UDP套接口而言(TCP不支持多播)。
SO_REUSEPORT選項有如下語義:
    此選項允許完全重複捆綁,但僅在想捆綁相同IP地址和端口的套接口都指定了此套接口選項才行。
    如果被捆綁的IP地址是一個多播地址,則SO_REUSEADDR和SO_REUSEPORT等效。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章