可以多個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配置大致如下:
後來有人說了,走port listener的方式要走7層交換,走unix socket file的方式只要走3層,所以性能更好。於是,就有了下面的改進方案: - 多個server 進程,每個server進程對應一個unix socket file,前面依然由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;
}
啟動大致如下:
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配置大致如下:
原本,事情到這已經結束了。突然,不知道某個奇葩的人提出了這樣一個方式: - 多個server 進程,共同對應一個unix socket file,前面走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
}
啟動配置大致如下:
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配置大致如下:
好吧,當時我看到的時候就感覺有問題,不過系統從這樣部署到現在已經工作有接近1年的時間,據其他同事說,目前雖然負載不大,每天也就在20w+的pv,但是確實工作正常。但我始終覺得這種方式有問題。所以,去google搜索了一下,但是貌似沒有相關的情況。所以,就來知乎詢問一下。求解啊!
upstream webserver {
server unix:/var/3w/webserver.sock
}
樓上幾位說 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-tSocket Sharding in NGINXhttps://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怎麼讀?