Java程序員也應該知道的係統知識係列之網卡
作者:林昊
對於編寫分布式Java應用的同學而言,網卡的一些知識也是必須掌握的,例如什麼是網卡的bonding模式,網卡的中斷處理,os相關的參數等。
機器上網卡的型號可通過lspci | grep -i ether來查看,同樣在看到網卡的型號後可通過google了解下網卡的狀況,對於Java應用而言,主要需要關注的是網卡是否支持多隊列,這個可以通過lspci -vvv | grep -i msi-x來查看網卡是否支持多隊列,以及支持多少個隊列,具體多隊列的作用後麵講。
機器上網卡的bonding模式是需要了解的,原因是bonding模式對應用可用的網絡帶寬會有直接影響,網卡的bonding模式可通過cat /proc/net/bonding/*bond*來查看,看到的信息會類似如下:
Bonding Mode: fault-tolerance (active-backup)
上麵這種模式代表一塊網卡是激活的,另一塊是備份狀態,也就是應用能用的網絡帶寬是一塊網卡,例如網卡是千兆的,那意味著應用最多能用的網絡帶寬是1000m bits(這個還取決於機器所在的網絡環境的收斂比),linux支持7種網卡的bonding模式,感興趣的話可以google看下。
除了bonding模式外,和應用比較相關的另外一點就是網卡的中斷處理,這個在之前有專門寫過一篇文章,具體請見前麵的文章。
除了硬件層麵外,os層麵有幾個和網絡相關的重要參數:
net.core.somaxconn
net.ipv4.tcp_max_syn_backlog
這兩個參數是用來控製並發建連接時等待的隊列長度,當隊列滿了後,後續連接會直接失敗,對於需要支撐較大量的並發連接的server端而言就很重要了,但對於java程序而言,如果是直接new ServerSocket這種的,會把backlog這個值設置為50,因此最好是在寫程序的時候能設置下這個值,無論是直接基於java寫,還是基於一些通訊框架寫,backlog這個都是支持設置的,具體也可以看看這個關於backlog的case。
由於每建一個連接其實都是打開一個文件,因此需要關注下進程的open files的限製,可通過cat /proc/[pid]/limits來查看其中的Max open files,這個值建議稍微配大一些(否則很容易出現too many open files的錯誤),可通過修改/etc/security/limits.conf或直接ulimit -n來設置。
net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle
net.ipv4.tcp_tw_timeout
這三個參數主要是用來控製time_out連接的回收的,如果不配置好可能會出現time_wait太多導致連接建不了的現象,其中tcp_tw_recycle最好關閉,在通過lb設備連接的情況下,如果打開這個參數,有些時候會出問題。
net.ipv4.tcp_wmem
net.ipv4.tcp_rmem
讀寫緩衝區,這個值如果太小,會導致在讀寫的時候出現網卡阻塞的現象,例如寫就會出現寫不進網卡的現象,而由於linux默認的值通常太小,尤其是在局域網環境下,由於網絡的不可確定性,Java通信程序在編寫的時候一定要注意限流,避免由於send buffer滿的情況下java heap也被耗光的現象(由於sendbuffer被寫滿,通常發不出去的數據就會緩存在java heap裏)。
網卡的資源使用率狀況可以通過sar -n DEV來查看,需要關注的重點還是網絡帶寬,另外要關注的一點是cpu上處理網卡中斷的均衡性狀況,這個通過觀看cpu的hi/si指標可以看出。
對於編寫通信框架或RPC框架的同學而言,小包跑滿網卡帶寬通
常是目標(因為大包的話很容易就跑滿了),但要做到難度還是不小的,具體可見我做的一個開源rpc框架nfs-rpc的優化記錄(ps: 歡迎大家來一起做優化)。
在網卡帶寬跑滿的情況下,通常可選擇優化方法是壓縮,壓縮通常可選擇的是java自帶的zip、lzo以及google的snappy,相比而言其實基本就是在lzo和snappy中做選擇就可,在優化了的情況下網絡帶寬仍跑滿而其他資源比較富餘的話,可以考慮網卡多塊激活,或升級到更高帶寬的網卡,例如千兆到萬兆等,但這些優化就不僅僅是單機了,而是要整個結構配合。
最後更新:2017-04-03 07:57:07