By fireworks2@foxmail.com
找了大半天的資料,收穫也不多,其實還是自己思考更靠譜一些。
1. unix域的資料報服務是否可靠
man unix 手冊即可看到,unix domain socket 的資料報既不會丟失也不會亂序 (據我所知,在linux下的確是這樣)。不過最新版本的核心,仍然又提供了一個保證次序的類型 “ kernel 2.6.4 SOCK_SEQPACKET ”。
2. STREAM 和 DGRAM 的主要區別
既然資料報不丟失也可靠,那不是和 STREAM 很類似麼。我理解也確實是這樣,而且我覺得 DGRAM 相對還要好一些,因為發送的資料可以帶邊界。二者另外的區別在於收發時的資料量不一樣,基於 STREAM 的通訊端,send 可以傳入超過 SO_SNDBUF 長的資料,recv 時同 TCP 類似會存在資料粘連。
採用阻塞方式使用API,在unix domain socket 下調用 sendto 時,如果緩衝隊列已滿,會阻塞。而UDP因為不是可靠的,無法感知對端的情況,即使對端沒有及時收取資料,基本上sendto都能立即返回成功(如果發端瘋狂sendto就另當別論,因為過快地調用sendto在慢速網路的環境下,可能撐爆通訊端的緩衝區,導致sendto阻塞)。
3. SO_SNDBUF 和 SO_REVBUF
對於 unix domain socket,設定 SO_SNDBUF 會影響 sendto 最大的報文長度,但是任何針對 SO_RCVBUF 的設定都是無效的 。實際上 unix domain socket 的資料報還是得將資料放入核心所申請的記憶體塊裡面,再由另一個進程通過 recvfrom 從核心讀取,因此具體可以發送的資料報長度受限於核心的 slab 策略 。在 linux 平台下,早先版本(如 2.6.2)可發送最大資料報長度約為 128 k ,新版本的核心支援更大的長度。
4. 使用 DGRAM 時,緩衝隊列的長度
有幾個因素會影響緩衝隊列的長度,一個是上面提到的 slab 策略,另一個則是系統的核心參數 /proc/sys/net/unix/max_dgram_qlen。緩衝隊列長度是這二者共同決定的。
如 max_dgram_qlen 預設為 10,在資料報較小時(如1k),先掛起接收資料的進程後,仍可以 sendto 10 次並順利返回;
但是如果資料報較大(如120k)時,就要看 slab “size-131072” 的 limit 了。
5. 使用 unix domain socket 進行處理序間通訊 vs 其他方式
· 需要先確定作業系統類型,以及其所對應的最大 DGRAM 長度,如果有需要傳送超過該長度的資料報,建議拆分成幾個發送,接收後組裝即可(不會亂序,個人覺得這樣做比用 STREAM 再切包方便得多)
· 同管道相比,unix 域的資料報不但可以鑑效組資料的邊界,還不會碰到在寫入管道時的原子性問題。
· 同共用記憶體相比,不能獨立於進程緩衝大量資料,但是卻避免了同步互斥的考量。
· 同普通 socket 相比,開銷相對較小(不用計算前序),DGRAM 的報文長度可以大於 64k,不過不能像普通 socket 那樣將進程切換到不同機器 。
6. 其他
其實在本機 IPC 時,同普通 socket 的 UDP 相比,unix domain socket 的資料報只不過是在收發時分別少計算了一下校正和而已,原生 UDP 會走 lo 介面,不會進行 IP 分區,也不會真正跑到網卡的鏈路層上去(不會佔用網卡硬體) 。也就是說,在本機上使用普通的 socket UDP,只是多耗了一些 CPU(之所以說一些,是因為校正和的計算很簡單),此外原生 UDP 也可以保證資料不丟失、不亂序 。
從我個人的經驗來看,即便是高並發的網路伺服器,單純因為收發包造成的 CPU 佔用其實並不算多(其中收包佔用的 CPU 從 %si 可見一斑,因為收包需通過非強制中斷實現的),倒是網卡頻寬、磁碟IO、後台邏輯、記憶體使用量等問題往往成為主要矛盾。
所以,在沒有長時緩衝通訊資料的需求時,可以考慮通過 UDP 來實現本地進程間 IPC,這樣也便於切換機器。 (也不必去操心 unix domain socket 資料報的最大長度了,呵呵)對於較長的報文,可以切分成小的,再重新組裝,不過這樣做僅適用於本機通訊,如果還要考慮以後遷移機器,那還是老老實實地 TCP 吧。 (本地 TCP 耗用資源的情況不得而知,沒有做過充分的測試,不過本地 TCP 自身的一些收發包操作一般也不構成瓶頸)
---在 google 時尋找到的其他資源也一併列在這裡---
setsockopt 設定 SO_SNDBUF SO_RCVBUF 時的冗餘分配:
http://www.tux.org/lkml/
unix域通訊端的使用:
http://www.cnblogs.com/skynet/archive/2010/12/04/1881236.html
http://hi.baidu.com/studyarea/blog/item/b007f4450a2a9e38879473ca.html