重学TCP协议(12)SO_REUSEADDR、SO_REUSEPORT、SO_LINGER
1. SO_REUSEADDR
假如服務端出現故障,主動斷開連接以后,需要等 2 個 MSL 以后才最終釋放這個連接,而服務重啟以后要綁定同一個端口,默認情況下,操作系統的實現都會阻止新的監聽套接字綁定到這個端口上。啟用 SO_REUSEADDR 套接字選項可以解除這個限制。
2. SO_REUSEPORT
默認情況下,一個 IP、端口組合只能被一個套接字綁定,Linux 內核從 3.9 版本開始引入一個新的 socket 選項 SO_REUSEPORT,又稱為 port sharding,允許多個套接字監聽同一個IP 和端口組合。
2.1 多進程網絡模型
- 主進程 + 多個 worker 子進程監聽相同的端口(導致驚群問題)
- 多進程 + REUSEPORT
2.2 驚群問題
多進程/多線程同時監聽同一個套接字,當有網絡事件發生時,所有等待的進程/線程同時被喚醒,但是只有其中一個進程/線程可以處理該網絡事件,其它的進程/線程獲取失敗重新進入休眠。
2.3 accept系統調用的驚群問題
在Linux 2.6之前,會出現驚群問題。而在后面的版本中,引入了WQ_FLAG_EXCLUSIVE 選項解決了 accept 調用的驚群問題。
2.4 epoll系統調用的驚群問題
當有新的網絡事件發生時,阻塞在 epoll_wait 的多個進程同時被喚醒。在這種情況下,epoll 的驚群還是存在的。
2.5 SO_REUSEPORT原理
內核為處于 LISTEN 狀態的 socket 分配了大小為 32 哈希桶。監聽的端口號經過哈希算法運算打散到這些哈希桶中,相同哈希的端口采用拉鏈法解決沖突。
當收到客戶端的 SYN 握手報文以后,會根據目標端口號的哈希值計算出哈希沖突鏈表
對于設置了 SO_REUSEPORT 選項的 socket 經過二次哈希找到對應的 SO_REUSEPORT group,從中隨機選擇一個進行處理。
2.6 SO_REUSEPORT作用
- 內核有數據到來的時候就會把請求均衡的分給不同的socket,也就是不同的線程了,這樣內核可以自動的做到負載均衡
- 支持滾動升級
2.7 SO_REUSEPORT安全性
出于安全性考慮,防止端口劫持
- 只有effective-user-id相同的服務器進程才能監聽同一ip:port
- 只有第一個啟動的進程啟用了 SO_REUSEPORT 選項,后面啟動的進程才可以綁定同一個端口。
3. SO_LINGER
設置函數close()關閉TCP連接時的行為。缺省close()的行為是,如果有數據殘留在socket發送緩沖區中則系統將繼續發送這些數據給對方,等待被確認,然后返回。
SO_LINGER選項使用如下結構:
struct linger {int l_onoff;int l_linger; };-
a.立即關閉該連接,通過發送RST分組(而不是用正常的FIN|ACK|FIN|ACK四個分組)來關閉該連接。至于發送緩沖區中如果有未發送完的數據,則丟棄。主動關閉一方的TCP狀態則跳過TIMEWAIT,直接進入CLOSED。
-
b.將連接的關閉設置一個超時。如果socket發送緩沖區中仍殘留數據,進程進入睡眠,內核進入定時狀態去盡量去發送這些數據。
在超時之前,如果所有數據都發送完且被對方確認,內核用正常的FIN|ACK|FIN|ACK四個分組來關閉該連接,close()成功返回。
如果超時之時,數據仍然未能成功發送及被確認,用上述a方式來關閉此連接。close()返回EWOULDBLOCK。
參考文章
深入理解 TCP 協議:從原理到實戰
總結
以上是生活随笔為你收集整理的重学TCP协议(12)SO_REUSEADDR、SO_REUSEPORT、SO_LINGER的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 周公解梦梦到自己生小孩是什么意思
- 下一篇: 梦到同学被蛇咬是什么意思