前段時間線上環境遇到一個問題,在 POST
數據通過 LVS
的時候,會特別慢,100K 的數據每每超過 5 秒,後來研究發現 LVS
在 Centos6(2.6.29-2.6.39)
下,若是開啓 GRO
,會大量丟包。後端
線上服務器採用 LVS
做爲負載均衡和高可用,LVS
用的是 DR
模式。新建 LVS
使用後發現,在上傳數據時,小數據會很快,大數據會很慢。若是繞過 LVS
直接到後端,就沒有這個問題,因此問題定位在 LVS
所在的服務器。服務器
如今測試環境重現以下,上傳兩個文件,一個 10k,一個 100k,10k 的只須要 0.009
秒,100k 居然要接近 10
秒:網絡
[root@chengqm test_upload]# ll -h total 112K -rw-r--r--. 1 root root 100K Mar 31 21:26 100k_file -rw-r--r--. 1 root root 10K Mar 31 21:25 10k_file [root@chengqm test_upload]# time curl 10.0.1.188:22333/upload -F "myfile=@./10k_file" ok real 0m0.009s user 0m0.001s sys 0m0.003s [root@chengqm test_upload]# time curl 10.0.1.188:22333/upload -F "myfile=@./100k_file" ok real 0m9.785s user 0m0.000s sys 0m0.006s
在 LVS
服務器上執行 tcpdump host 10.0.1.188 -w lvs.pcap
捉包,並用 Wireshark
打開,發現有大量的重傳現象和 Fragmentation needed
要求分片的控制報文。負載均衡
接着使用 netstat -i
檢查 Client
和 LVS
網卡的 MTU
是否一致,發現相關服務器的 MTU
值均爲 1500
,網絡工程師告知網絡設備 MTU
沒有改動,排除機器 MTU
不一致引發的問題。curl
搜索關鍵詞 lvs fragmentation needed
發現一個叫 GRO
的功能可能會引發 LVS
機器丟包tcp
使用 ethtool -k 網卡名
查看網卡配置,對比正常 LVS
的網卡,發現有問題的網卡確實開啓了 GRO
功能性能
[root@chengqm-lvs ~]# ethtool -k eth0| grep 'generic-receive-offload' generic-receive-offload: on
手動關閉 GRO
功能測試
[root@chengqm-lvs ~]# ethtool -K eth0 gro off
再次上傳數據大數據
[root@chengqm test_upload]# time curl 10.0.1.188:22333/upload -F "myfile=@./100k_file" ok real 0m0.031s user 0m0.001s sys 0m0.009s
問題解決,恢復正常url
MTU 通常都是 1500 字節,若是一個包超過了 MTU ,就會被分片,對於當前網卡性能來講,這個數值過小了,如今 10Gbps 的網卡都廣泛使用了,若是 10Gbps 的網卡滿載地來跑,一個完整的數據包會被分片 800w 片。咱們能夠經過修改 MTU 來減小分片,可是修改 MTU 涉及的設備就多了,不可控。因而有了經過網卡來間接實現提升 MTU 的方案,這就是 GRO
。
若是開啓 GRO
,在網卡中將知足必定的條件的包,將分片的包組裝合併了,才一次性交給上面的協議棧。在 2.6.29
後 若是網卡和驅動都支持,那麼會默認開啓 GRO
功能。
聽說在 2.6.29-2.6.39
版本中, LVS 內核模塊在處理>MTU
的數據包時,會丟棄,因此才能看到一堆重發的包和fragmentation needed
。
MTU
值。LVS
所在機器的系統內核。聽從先恢復正常使用的原則,咱們直接關閉了 GRO
,上述兩個方案可做爲後續調整的方向。方案 1 涉及的設備比較多,難以評估風險和影響,因此暫不考慮。方案 2 可做爲後期調整方向。
須要注意的一個地方是,若是使用的是雲服務器,須要同時關閉宿主機的 GRO
,若是網卡有作 bond
,須要在真實網卡中關閉 GRO
。