可以多個server進程同時監聽一個unix socket文件么?

先說一下大家通常的方案:

- 多個server 進程,每個server進程監聽一個埠,前面由nginx進行代理。

啟動大致如下:

python webserver --app_port=9101
python webserver --app_port=9102
python webserver --app_port=9103
python webserver --app_port=9104

nginx配置大致如下:

upstream webserver {
server 127.0.0.1:9101;
server 127.0.0.1:9102;
server 127.0.0.1:9103;
server 127.0.0.1:9104;
}

後來有人說了,走port listener的方式要走7層交換,走unix socket file的方式只要走3層,所以性能更好。於是,就有了下面的改進方案:

- 多個server 進程,每個server進程對應一個unix socket file,前面依然由nginx代理。

啟動大致如下:

python webserver --app_sockfile=/var/3w/9101.sock
python webserver --app_sockfile=/var/3w/9102.sock
python webserver --app_sockfile=/var/3w/9103.sock
python webserver --app_sockfile=/var/3w/9104.sock

nginx配置大致如下:

upstream webserver {
server unix:/var/3w/9101.sock
server unix:/var/3w/9102.sock
server unix:/var/3w/9103.sock
server unix:/var/3w/9104.sock
}

原本,事情到這已經結束了。突然,不知道某個奇葩的人提出了這樣一個方式:

- 多個server 進程,共同對應一個unix socket file,前面走nginx代理

啟動配置大致如下:

python webserver --app_sockfile=/var/3w/webserver.sock
python webserver --app_sockfile=/var/3w/webserver.sock
python webserver --app_sockfile=/var/3w/webserver.sock
python webserver --app_sockfile=/var/3w/webserver.sock

nginx配置大致如下:

upstream webserver {
server unix:/var/3w/webserver.sock
}

好吧,當時我看到的時候就感覺有問題,不過系統從這樣部署到現在已經工作有接近1年的時間,據其他同事說,目前雖然負載不大,每天也就在20w+的pv,但是確實工作正常。但我始終覺得這種方式有問題。所以,去google搜索了一下,但是貌似沒有相關的情況。所以,就來知乎詢問一下。求解啊!


樓上幾位說 reuse 的同學,麻煩寫寫代碼好嗎,不懂別亂說。reuse 是用在 埠處於timewait 後能否被複用好嗎,和這個問題有毛關係啊。

回答問題,進程先listen,然後fork 多個子進程,每個子進程再accept 就會出現這種狀況。connect的連接具體被哪個子進程accept返回是由內核分發。unp,apue 上都有講。

問題太簡單本不想回答,只要被樓上幾位說reuse的朋友氣到啦。


高票的答案其實是錯的,在linux 3.9以後kernel引入了SO_REUSEPORT,可以允許多個進程綁定同一個埠,nginx 1.9.1 引入這個feature,可大幅提升性能

SO_REUSEPORT vs SO_REUSEADDR

http://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t

Socket Sharding in NGINX

https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/


猛的一看竟然是兩年前的問題了,看了各位義憤填膺的回答,簡單發表下自己的看法,reuseaddr是用來去掉2MSL的,MSL請看tcp協議,簡單來講,當某個綁定了套接字127.0.0.1:8080的進程stop後,假如沒有使用reuseaddr,該進程不能立刻重新運行,反之,則可以立刻running。 reuseport,也是setsockopt來設置套接字屬性的,沒用過,不懂。

至於多個進程能不能綁定同一個套接字,實踐告訴我,是可以的,listen完再fork,所有進程都會佔有那個listen的套接字,2.6內核以前,當新的鏈接握手完成後,所有fork出來的父子進程都會喚醒,但是,只有第一個被schedule的進程才會真正去處理鏈接,其他的進程睜開眼一看沒自己什麼事,又接著去睡覺了,俗稱驚群。2.6以後(沒記錯的話是2.6,還是3.0來著???)內核稍稍優化下,每次只會取待調度隊列的第一個進程來喚醒。所以,我認為,這也叫多進程綁定同一個套接字。

重點來了,觀察題主的截圖,使用的是unix域套接字,域套接字跟埠什麼的,有什麼關係了???域套接字綁定的sockaddr_in.addr應該是個字元串吧,有名管道和套接字的結合使用,經常用來進行進程間通信。

睡前瞎逼逼一通,和諧社會,不喜勿噴


在查相關問題找到這裡,然而贊同最多的竟然是錯的那個-_-#

# 2016-11-04補充

剛答完就覺得sb了:我在挖墳!沒想到竟引來後繼挖墳人。

# 2016-11-09補充

最高票換人了,木問題了。

PS. 後邊在說的是SO_REUSEPORT的作用哈,是可以用來多進程BIND同一埠的。


可以的,完全沒有問題。

因為這是使用了 UNIX 域協議,甚至算不上是一個協議族,只是一種 IPC 而已。

講 reuse 的,不管是 port 還是 addr,都跟 UNIX 域協議沒關係。


可以,參考nginx


推薦閱讀:

Django和Flask這兩個框架在設計上各方面有什麼優缺點?
Vim 中如何對 Python 進行代碼補全?
GitHub 上有哪些值得關注的 Django 項目?
Django 學習順序及入門要求?
django怎麼讀?

TAG:Python | Tornado | Django框架 |