MySQL 調優基礎(五) Linux網絡

1、TCP/IP模型

咱們通常知道OSI的網絡參考模型是分爲7層:「應表會傳網數物」——應用層,表示層,會話層,傳輸層,網絡層,數據鏈路層,物理層。而實際的Linux網絡層協議是參照了OSI標準,可是它實現爲4層:應用層,傳輸層,網絡層,網絡接口層。OSI的多層對應到了實際實現中的一層。咱們最爲關注的是傳輸層和網絡層。通常而言網絡層也就是IP層,負責IP路由尋址等等細節,而傳輸層TCP/UDP負責數據的可靠/快速的傳輸功能。html

網絡的實際運行過程就是發送方,從高層向底層,根據協議對數據進行一層一層的封包,每一層加上該層協議的header;而接收方,從底層向高層,不斷的解封數據包,每一層去掉該層的協議的header,而後最高層的應用層獲得應用層數據:mysql

每一層添加的 Header(TCP/UDP Header, IP Header, Data Link Header) 都是爲了實現該層協議服務而必須存在的協議相關數據。linux

2、Socket Buffer

發生方發送數據,接收方接受數據,那麼雙方必須存在一個保存數據的buffer,稱爲Socket Buffer,TCP/IP的實現都是放在kernel中的,因此Socket Buffer也是在kernel中的。Socket Buffer的大小配置對網絡的性能有很大的影響,相關參數以下:nginx

1)/proc/sys/net/ipv4/tcp_mem: 這是一個系統全局參數,表示全部TCP的buffer配置。有三個值,單位爲內存頁(一般爲4K),第一個值buffer值的下限,第二個值表示內存壓力模式開始對buffer應於壓力的上限;第三個值內存使用的上限,超過期,可能會丟棄報文。redis

2)/proc/sys/net/ipv4/tcp_rmen: r 表示receive,也有三個值,第一個值爲TCP接收buffer的最少字節數;第二個是默認值(該值會被rmem_default覆蓋);第三個值TCP接收buffer的最大字節數(該值會被rmem_max覆蓋);sql

3)/proc/sys/net/ipv4/tcp_wmem: w表示write,也就是send。也有三個值,第一個值爲TCP發送buffer的最少字節數;第二個是默認值(該值會被wmem_default覆蓋);第三個值TCP發送buffer的最大字節數(該值會被wmem_max覆蓋);windows

4)/proc/sys/net/core/wmem_default: TCP數據發送窗口默認字節數;瀏覽器

5)/proc/sys/net/core/wmem_max: TCP數據發送窗口最大字節數;緩存

6)/proc/sys/net/core/rmem_default: TCP數據接收窗口默認字節數;服務器

7)/proc/sys/net/core/rmem_max: TCP數據接收窗口最大字節數;

注意:除了tcp_mem單位爲內存頁以外,其它幾個單位都是字節;並且tcp_mem是全局配置,其它幾個都是針對每個TCP鏈接的配置參數。

3、網絡 NAPI, Newer newer NAPI

NAPI是爲了解決網絡對CPU的影響而引入的。

Every time an Ethernet frame with a matching MAC address arrives at the interface, there will be a hard interrupt. Whenever a CPU has to handle a hard interrupt, it has to stop processing whatever it was working on and handle the interrupt, causing a context switch and the associated flush of the processor cache. While you might think that this is not a problem if only a few packets arrive at the interface, Gigabit Ethernet and modern applications can create thousands of packets per second, causing a large number of interrupts and context switches to occur.

Because of this, NAPI was introduced to counter the overhead associated with processing network traffic. For the first packet, NAPI works just like the traditional implementation as it issues an interrupt for the first packet. But after the first packet, the interface goes into a polling mode. As long as there are packets in the DMA ring buffer of the network interface, no new interrupts will be caused, effectively reducing context switching and the associated overhead.

可見:NAPI 能夠有效的減小網絡對CPU中斷而致使的上下文切換次數,減輕致使的CPU性能損耗。

4、Netfilter

Linux內核中的防火牆實現模塊。也就是咱們使用iptables調用的功能。提供了包過濾和地址轉換功能。

5、TCP/IP 的三次握手創建鏈接和四次揮手結束鏈接

5.1  三次握手創建鏈接:

1)第一次握手:創建鏈接時,客戶端A發送SYN包(SYN=j)到服務器B,並進入SYN_SEND狀態,等待服務器B確認。

2)第二次握手:服務器B收到SYN包,必須發生一個ACK包,來確認客戶A的SYN(ACK=j+1),同時本身也發送一個SYN包(SYN=k),即SYN+ACK包,此時服務器B進入SYN_RECV狀態。

3)第三次握手:客戶端A收到服務器B的SYN+ACK包,向服務器B發送確認包ACK(ACK=k+1),此包發送完畢,客戶端A和服務器B進入ESTABLISHED狀態,完成三次握手(注意,主動打開方的最後一個ACK包中可能會攜帶了它要發送給服務端的數據)。

總結三次握手,其實就是主動打開方,發送SYN,表示要創建鏈接,而後被動打開方對此進行確認,表示能夠,而後主動方收到確認以後,對確認進行確認;

5.2  四次揮手斷開鏈接:

因爲TCP鏈接是全雙工的,所以每一個方向都必須單獨進行關閉,TCP的雙方都要向對方發送一次 FIN 包,而且要對方對次進行確認。根據兩次FIN包的發送和確承認以將四次揮手分爲兩個階段:

第一階段:主要是主動閉方方發生FIN,被動方對它進行確認;  

1)第一次揮手:主動關閉方,客戶端發送完數據以後,向服務器發送一個FIN(M)數據包,進入 FIN_WAIT1 狀態;

                     被動關閉方服務器收到FIN(M)後,進入 CLOSE_WAIT 狀態;
2)第二次揮手:服務端發生FIN(M)的確認包ACK(M+1),關閉服務器讀通道,進入 LAST_ACK 狀態;客戶端收到ACK(M+1)後,關閉客戶端寫通道,

                     進入 FIN_WATI2 狀態;此時客戶端仍能經過讀通道讀取服務器的數據,服務器仍能經過寫通道寫數據。

第二階段:主要是被動關閉方發生FIN,主動方對它進行確認;

3)第三次揮手:服務器發送完數據,向客戶機發送一個FIN(N)數據包,狀態沒有變仍是 LAST_ACK;客戶端收到FIN(N)後,進入 TIME_WAIT 狀態

4)第四次揮手:客戶端返回對FIN(N)的確認段ACK(N+1),關閉客戶機讀通道(仍是TIME_WAIT狀態);

                     服務器收到ACK(N+1)後,關閉服務器寫通道,進入CLOSED狀態。

總結

四次揮手,其本質就是:

主動關閉方數據發生完成以後 發生FIN,表示我方數據發生完,要斷開鏈接,被動方對此進行確認;

而後被動關閉方在數據發生完成以後 發生FIN,表示我方數據發生完成,要斷開鏈接,主動方對此進行確認

5.3  CLOSE_WAIT狀態的緣由和處理方法:

由上面的TCP四次揮手斷開鏈接的過程,能夠知道 CLOSE_WAIT 是主動關閉方發生FIN以後,被動方收到 FIN 就進入了 CLOSE_WAIT狀態,此時若是被動方沒有調用 close() 函數來關閉TCP鏈接,那麼被動方服務器就會一直處於 CLOSE_WAIT 狀態(等待調用close函數的狀態);

因此 CLOSE_WAIT 狀態不少的緣由有兩點:

1)代碼中沒有寫關閉鏈接的代碼,也就是程序有bug; 
2)該鏈接的業務代碼處理時間太長,代碼還在處理,對方已經發起斷開鏈接請求; 也就是客戶端由於某種緣由先於服務端發出了FIN信號,致使服務端被動關閉,若服務端不主動關閉socket發FIN給Client,此時服務端Socket會處於CLOSE_WAIT狀態(而不是LAST_ACK狀態)。

CLOSE_WAIT 的特性

因爲某種緣由致使的CLOSE_WAIT會維持至少2個小時的時間(系統默認超時時間的是7200秒,也就是2小時)。若是服務端程序因某個緣由致使系統形成一堆 CLOSE_WAIT消耗資源,那麼一般是等不到釋放那一刻,系統就已崩潰。CLOSE_WAIT 的危害還包括是TOMCAT失去響應等等。

要解決 CLOSE_WAIT 過多致使的問題,有兩種方法:

1)找到程序的bug,進行修正;

2)修改TCP/IP的keepalive的相關參數來縮短CLOSE_WAIT狀態維持的時間;

TCP鏈接的保持(keepalive)相關參數

1> /proc/sys/net/ipv4/tcp_keepalive_time  對應內核參數 net.ipv4.tcp_keepalive_time

含義:若是在該參數指定的秒數內,TCP鏈接一直處於空閒,則內核開始向客戶端發起對它的探測,看他是否還存活着;

2> /proc/sys/net/ipv4/tcp_keepalive_intvl  對應內核參數 net.ipv4.tcp_keepalive_intvl

含義:以該參數指定的秒數爲時間間隔,向客戶端發起對它的探測;

3> /proc/sys/net/ipv4/tcp_keepalive_probes  對應內核參數 net.ipv4.tcp_keepalive_probes

含義:內核發起對客戶端探測的次數,若是都沒有獲得相應,那麼就判定客戶端不可達或者已關閉,內核就關閉該TCP鏈接,釋放相關資源;

因此 CLOSE_WAIT 狀態維持的秒數 = tcp_keepalive_time + tcp_keepalive_intvl * tcp_keepalive_probes

因此適當的 下降 tcp_keepalive_time, tcp_keepalive_intvl,tcp_keepalive_probes 三個值就能夠減小 CLOSE_WAIT:

修改方法:

sysctl -w net.ipv4.tcp_keepalive_time=600   
sysctl -w net.ipv4.tcp_keepalive_probes=3
sysctl -w net.ipv4.tcp_keepalive_intvl=5
sysctl -p

修改會暫時生效,從新啓動服務器後,會還原成默認值。修改以後,進行觀察一段時間,若是CLOSE_WAIT減小,那麼就能夠進行永久性修改:

在文件 /etc/sysctl.conf 中的添加或者修改爲下面的內容:

net.ipv4.tcp_keepalive_time = 1800 
net.ipv4.tcp_keepalive_probes = 3 
net.ipv4.tcp_keepalive_intvl = 15

這裏的數值比上面的要大,由於上面的測試數據有點激進。固然數據該大以後效果很差,仍是可使用上面激進的數據。

修改以後執行: sysctl -p 使修改立刻生效。

5.4  TIME_WAIT狀態的緣由和處理方法:

TIME_WAIT和CLOSE_WAIT不同,默認的TIME_WAIT原本就比較大,可是默認的CLOSE_WAIT應該很短纔對。

TIME_WAIT發生在TCP四次揮手的第二階段:被動關閉方發生FIN(N),主動方收到該FIN(N),就進入 TIME_WAIT 狀態,而後發生ACK(N+1)。

進入 TIME_WAIT 以後,主動關閉方會等待 2MSL(Maximum Segment Lifetime 報文最大存活時間)的時間,才釋放本身佔有的端口等資源。爲何呢?

這是由於,若是最後的ACK(N+1)沒有被被動方收到的話,被動方會從新發生一個FIN(N2),那麼主動方再次發生一個確認ACK(N2+1),因此這樣一來就要用使主動關閉方在 TIME_WAIT 狀態等待 2MSL 的時長。

若是你的 TIME_WAIT 狀態的TCP過多,佔用了端口等資源,那麼能夠經過修改TCP內核參數進行調優:

TCP 鏈接的 TIME_WATI相關參數:

1)/proc/sys/net/ipv4/tcp_tw_reuse  對應的內核參數:net.ipv4.tcp_tw_reuse

含義:是否可以從新啓用處於TIME_WAIT狀態的TCP鏈接用於新的鏈接;啓用該resuse的同時,必須同時啓用下面的快速回收recycle!

2)/proc/sys/net/ipv4/tcp_tw_recycle 對應的內核參數:net.ipv4.tcp_tw_recycle

含義:設置是否對TIME_WAIT狀態的TCP進行快速回收;

3)/proc/sys/net/ipv4/tcp_fin_timeout 對應的內核參數:net.ipv4.tcp_fin_timeout

含義:主動關閉方TCP保持在FIN_WAIT_2狀態的時間。對方可能會一直不結束鏈接或不可預料的進程死亡。默認值爲 60 秒。

修改方法和 keepalive 的相關參數同樣:

sysctl -w net.ipv4.tcp_tw_reuse=1   
sysctl -w net.ipv4.tcp_tw_recycle=1
sysctl -w net.ipv4.tcp_fin_timeout=30
sysctl -p

永久修改方法,也是修改 /etc/sydctl.conf:

net.ipv4.tcp_tw_reuse=1   
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_fin_timeout=30

sysctl -p 是修改生效。

若是是Windows Server,則能夠修改:TcpTimedWaitDelay  和 MaxUserPort;具體參見:http://www.cnblogs.com/digdeep/p/4779544.html

5.5  查看 TCP 鏈接處於各類狀態的鏈接數量:

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 297
ESTABLISHED 53
CLOSE_WAIT 5

windows 平臺實現相似功能:

netstat -n | find /i "time_wait" /c
netstat -n | find /i "close_wait" /c

一個一個的狀態來統計。

6、TCP/IP transfer window(傳輸窗口,滑動窗口)

Basically, the TCP transfer window is the maximum amount of data a given host can send or receive before requiring an acknowledgement from the other side of the connection. The window size is offered from the receiving host to the sending host by the window size field in the TCP header. Using the transfer window, the host can send packets more effectively because the sending host doesn't have to wait for acknowledgement for each sending packet. It enables the network to be utilized more. Delayed acknowledgement also improves efficiency. TCP windows start small and increase slowly with every successful acknowledgement from the other side of the connection.

傳輸窗口或者說滑動窗口,是指發送方在收到一個接收方的確認包以前,能夠發送的數據的總量。接收方經過TCP頭中的window size字段告訴發送方本身的能夠接受的 傳輸窗口是多大,而後發送方就會據此對傳輸窗口的大小進行優化。

7、TCP/IP Offload

若是網卡硬件支持checksum、tso等等功能,那麼就能夠將這些功能讓網卡來實現,從而下降CPU的負載。

1)checksum offload:爲了保證數據傳輸時沒有被破壞,IP/TCP/UDP都會對數據進行checksum,而後進行比較;該功能可讓網卡硬件實現;

2)TCP segmentation offload(TSO):若是傳輸的數據超過了網卡的MTU,那麼就必須拆分紅,也可讓網卡硬件來實現該功能;

8、多網卡綁定

Linux 內核支持將多個物理網卡綁定成一個邏輯網絡,從而進行網卡的負載均衡和網卡容錯的實現。

9、偵測網絡瓶頸和故障

查看Linux網絡狀況的命令通常有:netstat, iptraf, tcpdump 等等,其中netstat是使用的最多,也最好使用的工具。

9.1  使用 netstat 命令查看活動的網絡鏈接

netstat 查看信息根據協議不一樣和鏈接狀態不一樣分爲兩類:

1)根據協議 tcp -t, udp -u 進行顯示: netstat -ntap, netstat -nuap

-t 表示tcp 鏈接, -u 表示 udp 鏈接,以下所示

[root@localhost ~]# netstat -ntap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN      1373/vsftpd
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1352/sshd
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      1359/redis-server *
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      1078/rpcbind
tcp        0      0 192.168.1.200:22            192.168.1.3:50911           ESTABLISHED 1651/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50910           ESTABLISHED 1648/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:52950           ESTABLISHED 2304/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50909           ESTABLISHED 1645/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50908           ESTABLISHED 1642/sshd
tcp        0      0 :::22                       :::*                        LISTEN      1352/sshd
tcp        0      0 :::3306                     :::*                        LISTEN      2131/mysqld
tcp        0      0 :::6379                     :::*                        LISTEN      1359/redis-server *
tcp        0      0 :::111                      :::*                        LISTEN      1078/rpcbind
[root@localhost ~]# netstat -nuap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
udp        0      0 0.0.0.0:829                 0.0.0.0:*                               1078/rpcbind
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               1078/rpcbind
udp        0      0 0.0.0.0:631                 0.0.0.0:*                               1042/portreserve
udp        0      0 :::829                      :::*                                    1078/rpcbind
udp        0      0 :::111                      :::*                                    1078/rpcbind

2)其中對於TCP協議又能夠根據鏈接的狀態不一樣進行顯示: LISTEN -l ; 非 LISTEN 的,全部狀態的 -a

加 -l 選項表示僅僅顯示 listen 狀態的TCP鏈接,-a 選項表示全部狀態的TCP鏈接,默認只顯示ESTABLISHED 的TCP的鏈接,以下所示:

[root@localhost ~]# netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN      1373/vsftpd
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1352/sshd
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      1359/redis-server *
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      1078/rpcbind
tcp        0      0 :::22                       :::*                        LISTEN      1352/sshd
tcp        0      0 :::3306                     :::*                        LISTEN      2131/mysqld
tcp        0      0 :::6379                     :::*                        LISTEN      1359/redis-server *
tcp        0      0 :::111                      :::*                        LISTEN      1078/rpcbind
[root@localhost ~]# netstat -ntp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 192.168.1.200:22            192.168.1.3:50911           ESTABLISHED 1651/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50910           ESTABLISHED 1648/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:52950           ESTABLISHED 2304/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50909           ESTABLISHED 1645/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50908           ESTABLISHED 1642/sshd
[root@localhost ~]# netstat -ntap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN      1373/vsftpd
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1352/sshd
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      1359/redis-server *
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      1078/rpcbind
tcp        0      0 192.168.1.200:22            192.168.1.3:50911           ESTABLISHED 1651/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50910           ESTABLISHED 1648/sshd
tcp        0    608 192.168.1.200:22            192.168.1.3:52950           ESTABLISHED 2304/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50909           ESTABLISHED 1645/sshd
tcp        0      0 192.168.1.200:22            192.168.1.3:50908           ESTABLISHED 1642/sshd
tcp        0      0 :::22                       :::*                        LISTEN      1352/sshd
tcp        0      0 :::3306                     :::*                        LISTEN      2131/mysqld
tcp        0      0 :::6379                     :::*                        LISTEN      1359/redis-server *
tcp        0      0 :::111                      :::*                        LISTEN      1078/rpcbind

-n 表示 numeric 用數字顯示 ip 和 端口,而不是文字; -p 表示程序名稱;

還有 -c 能夠連續每秒顯示一次。

字段含義:

recv-Q 表示網絡接收隊列(receive queue)
表示收到的數據已經在本地接收緩衝,可是還有多少沒有被用戶進程取走,若是接收隊列Recv-Q一直處於阻塞狀態,多是遭受了拒絕服務 denial-of-service 攻擊。

send-Q 表示網路發送隊列(send queue)
發送了,可是沒有收到對方的Ack的, 還保留本地緩衝區.
若是發送隊列Send-Q不能很快的清零,多是有應用向外發送數據包過快,或者是對方接收數據包不夠快。

這兩個值一般應該爲0,若是不爲0多是有問題的。packets在兩個隊列裏都不該該有堆積狀態。可接受短暫的非0狀況。

netstat -s 顯示全部協議的鏈接的統計數據:

[root@localhost ~]# netstat -s
Ip:
    4677 total packets received
    0 forwarded
    0 incoming packets discarded
    4635 incoming packets delivered
    4938 requests sent out
Icmp:
    2 ICMP messages received
    0 input ICMP message failed.
    ICMP input histogram:
        destination unreachable: 2
    2 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 2
IcmpMsg:
        InType3: 2
        OutType3: 2
Tcp:
    0 active connections openings
    5 passive connection openings
    0 failed connection attempts
    0 connection resets received
    5 connections established
    4391 segments received
    4799 segments send out
    0 segments retransmited
    0 bad segments received.
    0 resets sent
Udp:
    0 packets received
    0 packets to unknown port received.
    0 packet receive errors
    137 packets sent
UdpLite:
TcpExt:
    13 delayed acks sent
    1 delayed acks further delayed because of locked socket
    557 packets header predicted
    2384 acknowledgments not containing data received
    1 predicted acknowledgments
    0 TCP data loss events
IpExt:
    InBcastPkts: 242
    InOctets: 408070
    OutOctets: 730869
    InBcastOctets: 68876

9.2  使用 iptraf 命令實時查看網絡

該命令顯示的是實時變化的網絡信息,直接執行  iptraf 能夠進入交互界面。

通常使用方法:iptraf -i eth0, iptraf -g eth0, iptraf -d eth0,  iptraf -l eth0 其中 eth0 能夠換成其它網卡,或者全部網卡 all

-i 表示 ip traffic, -g 表示 genral info, -d 表示 detail info 
比較經常使用的是: iptraf -d eth0, iptraf -d eth0 

其中顯示了:接收到的數據包的數量,發送的數據包的數量;還有網絡發包速率:incoming rates, outgoing rates。

9.3  使用 tcpdump 命令查看網絡 

使用 tcpdump 能夠對 網卡,host, 協議,端口等等進行過濾,指定只 查看指定的網絡信息。

下面的結果來自 192.168.1.3 的瀏覽器訪問虛擬機中的 192.168.1.200中的nginx的網絡包的發送狀況:

[root@localhost ~]# tcpdump -n -i eth0 host 192.168.1.200 and 192.168.1.3  and tcp port ! 22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:18:10.381925 IP 192.168.1.3.52970 > 192.168.1.200.http: Flags [S], seq 1845276991, win 8192, options [mss 1460,nop,wscale 2,nop,nop,s  ackOK], length 0
14:18:10.382024 IP 192.168.1.200.http > 192.168.1.3.52970: Flags [S.], seq 3067341762, ack 1845276992, win 14600, options [mss 1460,nop,  nop,sackOK,nop,wscale 6], length 0
14:18:10.382301 IP 192.168.1.3.52970 > 192.168.1.200.http: Flags [.], ack 1, win 16425, length 0
14:18:10.383170 IP 192.168.1.3.52970 > 192.168.1.200.http: Flags [P.], seq 1:352, ack 1, win 16425, length 351
14:18:10.383222 IP 192.168.1.200.http > 192.168.1.3.52970: Flags [.], ack 352, win 245, length 0
14:18:10.385314 IP 192.168.1.200.http > 192.168.1.3.52970: Flags [P.], seq 1:244, ack 352, win 245, length 243
14:18:10.386902 IP 192.168.1.200.http > 192.168.1.3.52970: Flags [P.], seq 244:856, ack 352, win 245, length 612
14:18:10.387324 IP 192.168.1.3.52970 > 192.168.1.200.http: Flags [.], ack 856, win 16211, length 0
14:18:20.392717 IP 192.168.1.3.52970 > 192.168.1.200.http: Flags [.], seq 351:352, ack 856, win 16211, length 1
14:18:20.392784 IP 192.168.1.200.http > 192.168.1.3.52970: Flags [.], ack 352, win 245, options [nop,nop,sack 1 {351:352}], length 0
^C
10 packets captured
12 packets received by filter
0 packets dropped by kernel

下面截圖簡單分析上面的結果:

首先是 192.168.1.3.52970 的瀏覽器 向 192.168.1.200.http 的服務器 發送一個 主動打開的 SYN(1845276991) 包;

接下來 192.168.1.200.http 的服務器 向 192.168.1.3.52970 的瀏覽器 發送一個 SYN + ACK 包,注意 ack=1845276992 = 1845276991 +1;

而後是 192.168.1.3.52970 的瀏覽器 向 192.168.1.200.http 的服務器 發送一個 ACK(1),而後向 服務器發送請求,seq 1:352從1到352恰好351個字節,和請求的長度: length 351 吻合;

接下來 服務器接受http請求以後,返回一個 ACK(352) ,確認收到瀏覽器的請求,而後開始處理,接着返回內容:

seq: 1:244, seq: 244:856, 響應請求,發送內容是用了兩個TCP鏈接,一塊兒發送了 855個字節給瀏覽器;

而後是 192.168.1.3.52970 的瀏覽器 接收到 856 個字節以後,返回一個 ACK(856)該服務器。

最後的兩個多是用於 瀏覽器和服務器之間保持keepalive而發送的。由於瀏覽器向服務器進發送一個字節(seq 351:352),而後服務器進行確認ACK(352)

能夠看到每個鏈接的頭部都帶有了 win 字段值(window size),在肯定傳輸窗口(滑動窗口)是須要使用到該字段;同時還能夠看到MSS值。

9.4  使用 sar -n 命令查看網絡 

sar 命令太強大了,CPU、內存、磁盤IO、網絡 均可以使用sar命令來查看。sar -n 專門用於網絡,使用方法以下:

sar -n { keyword [,...] | ALL }
              Report network statistics.

              Possible keywords are DEV, EDEV, NFS, NFSD, SOCK, IP, EIP, ICMP, EICMP, TCP,  ETCP,  UDP,  SOCK6,  IP6,  EIP6,
              ICMP6, EICMP6 and UDP6.

sar -n DEV: 查看全部網卡每秒收包,發包數量,每秒接收多少KB,發送多少KB:

[root@localhost ~]# sar -n DEV
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/12/2015      _i686_  (1 CPU)

09:19:33 AM       LINUX RESTART
... ...
11:10:02 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
11:20:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
11:20:01 AM      eth0     14.40     17.84      2.16      8.13      0.00      0.00      0.06
11:20:01 AM      eth1      0.25      0.03      0.02      0.01      0.00      0.00      0.00
11:30:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
11:30:01 AM      eth0      0.49      0.21      0.06      0.05      0.00      0.00      0.00
11:30:01 AM      eth1      0.23      0.04      0.01      0.01      0.00      0.00      0.00
Average:           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:         eth0      3.40      4.65      0.35      1.37      0.00      0.00      0.00
Average:         eth1      0.24      0.04      0.01      0.01      0.00      0.00      0.00

字段含義:rxpck/s txpck/s rxkB/s txkB/s 每秒收包,每秒發包,每秒接收KB數量,每秒發送KB數量;

sar -n EDEV: 查看網絡 錯誤,網絡超負載,網絡故障

[root@localhost ~]# sar -n EDEV
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/12/2015      _i686_  (1 CPU)

09:19:33 AM       LINUX RESTART
... ...
11:10:02 AM     IFACE   rxerr/s   txerr/s    coll/s  rxdrop/s  txdrop/s  txcarr/s  rxfram/s  rxfifo/s  txfifo/s
11:20:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
11:20:01 AM      eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
11:20:01 AM      eth1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
11:30:01 AM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
11:30:01 AM      eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
11:30:01 AM      eth1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:         eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:         eth1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

字段含義:

rxerr/s:Total number of bad packets received per second. 每秒接收的損壞的包
txerr/s:Total number of errors that happened per second while transmitting packets. 每秒發送的損壞的包
coll/s:    Number of collisions that happened per second while transmitting packets. 每秒發送的網絡衝突包數
rxdrop/s: Number of received packets dropped per second because of a lack of space in linux buffers. 每秒丟棄的接收包
txdrop/s: Number of transmitted packets dropped per second because of a lack of space in linux buffers. 每秒發送的被丟棄的包
txcarr/s:  Number of carrier-errors that happened per second while transmitting packets. carrier-errors 是啥意思?
rxfram/s: Number of frame alignment errors that happened per second on received packets. 
rxfifo/s:Number of FIFO overrun errors that happened per second on received packets. 接收fifo隊列發生過載錯誤次數(每秒)
txfifo/s:Number of FIFO overrun errors that happened per second on transmitted packets. 發送方的fifo隊列發生過載錯誤次數(每秒)

1)若是 coll/s 網絡衝突 持續存在,那麼可能網絡設備存在問題或者存在瓶頸,或者配置錯誤;

2)發生了 FIFO 隊列 overrun,表示 SOCKET BUFFER 過小;

3)持續的 數據包損壞,frame 損壞,可能預示着網絡設備出現部分故障,或者配置錯誤;

sar -n SOCK:查看系統佔用的全部的SOCKET端口 和 TIME_WAIT狀態鏈接數

[root@localhost ~]# sar -n SOCK
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/12/2015      _i686_  (1 CPU)

03:36:21 PM       LINUX RESTART

03:40:02 PM    totsck    tcpsck    udpsck    rawsck   ip-frag    tcp-tw
03:50:01 PM       105         8         3         0         0         0
04:00:02 PM       105         8         3         0         0         0
04:10:02 PM       108         8         4         0         0         0
04:20:01 PM       108         8         4         0         0         0
04:30:02 PM       105         8         3         0         0         0
04:40:01 PM       105         8         3         0         0         0
04:50:01 PM       105         8         3         0         0         0
Average:          106         8         3         0         0         0

With the SOCK keyword, statistics on sockets in use are reported (IPv4).  The following values are displayed:
totsck:  Total number of sockets used by the system.
tcpsck:  Number of TCP sockets currently in use.
udpsck: Number of UDP sockets currently in use.
rawsck: Number of RAW sockets currently in use.
ip-frag: Number of IP fragments currently in use.
tcp-tw: Number of TCP sockets in TIME_WAIT state.

9.5  使用 ifconfig 命令查看網絡 活動,錯誤,負載:

[root@localhost ~]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 08:00:27:07:21:AA
          inet addr:192.168.1.200  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe07:21aa/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8593 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9949 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:801191 (782.4 KiB)  TX bytes:2469866 (2.3 MiB)

errors: 發生的該網卡上的錯誤;dropped: 被丟棄的數量;overruns: socket buffer被用完的次數;frame:幀錯誤數量

10、網絡調優 和 故障排除

10.1  首先了解網絡的基本狀況:

1)查看各類狀態數量: netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

2)查看網絡error, overruns等待錯誤:ifconfig eth0, ifconfig all, sar -n EDEV, sar -n EDEV | grep eth0

3)查看網絡流量:sar -n DEV, sar -n DEV | grep eth0

10.2  確認網絡 duplex 和 speed 是否正確:

[root@localhost ~]# ethtool eth0
Settings for eth0:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Supported pause frame use: No
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Advertised pause frame use: No
        Advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: on
        MDI-X: off (auto)
        Supports Wake-on: umbg
        Wake-on: d
        Current message level: 0x00000007 (7)
                               drv probe link
        Link detected: yes

結果中, Speed: 1000Mb/s Duplex: Full 代表了是對的。若是是 Half, 100Mb/s 等等 會對性能影響極大。必須調整。

10.3  MTU 大小 調優

若是TCP鏈接的兩端的網卡和網絡接口層都支持大的 MTU,那麼咱們就能夠配置網絡,使用更大的mtu大小,也不會致使被 切割從新組裝發送。

配置命令:ifconfig eth0 mtu 9000 up

其實 除了 MTU ,還有一個 MSS(max segement size). MTU是網絡接口層的限制,而MSS是傳輸層的概念。其實這就是 TCP分段 和 IP分片 。MSS值是TCP協議實現的時候根據MTU換算而得(減掉Header)。當一個鏈接創建時, 鏈接的雙方都要通告各自的MSS值。

TCP分段發生在傳輸層,分段的依據是MSS, TCP分段是在傳輸層完成,並在傳輸層進行重組

IP分片發生在網絡層,分片的依據是MTU, IP分片由網絡層完成,也在網絡層進行重組。

其實還有一個 window size, 可是它是徹底不一樣的東西:

winsize is used for flow control. Each time the source can send out a number of segments without ACKs. You should check "sliding- 
window" to understand this. The value of win is dynamic since it's related to the remaining buffer size.

(參見:http://www.newsmth.net/nForum/#!article/CompNetResearch/4555)

區分:MTU, MSS, window size

10.4  調高網絡緩存

太小的網絡緩存,或致使頻繁的ACK確認包,以及致使 window size 很小,傳輸窗口也很小;太小的socket buffer對網絡性能影響嚴重。

Small socket buffers could cause performance degradation when a server deals with a lot of concurrent large file transfers. A clear performance decline will hanppen when using small socket buffers. A low value of rmem_max and wmem_max limit available socket buffer sizes even if the peer has affordable socket buffers available. This causes small window sizes and creates a performance ceiling for large data transfers. Though not included in this chart, no clear performance difference is observed for small data (less than 4 KB) transfer.

1)/proc/sys/net/ipv4/tcp_mem TCP全局存緩,單位爲內存頁(4k);

對應的內核參數:net.ipv4.tcp_mem ,能夠在 /etc/sysctl.conf 中進行修改;

2)/proc/sys/net/ipv4/tcp_rmem 接收buffer,單位爲字節

對應的內核參數:net.ipv4.tcp_rmem, 能夠在 /etc/sysctl.conf 中進行修改;

3)/proc/sys/net/ipv4/tcp_wmem 接收buffer,單位爲字節

對應的內核參數:net.ipv4.tcp_wmem, 能夠在 /etc/sysctl.conf 中進行修改;

-----------------------

4)/proc/sys/net/core/rmem_default 接收buffer默認大小,單位字節

對應內核參數:net.core.rmem_default, 能夠在 /etc/sysctl.conf 中進行修改;

5)/proc/sys/net/core/rmem_max 接收buffer最大大小,單位字節

對應內核參數:net.core.rmem_max, 能夠在 /etc/sysctl.conf 中進行修改;

6)/proc/sys/net/core/wmem_default 發送buffer默認大小,單位字節

對應內核參數:net.core.rmem_default, 能夠在 /etc/sysctl.conf 中進行修改;

7)/proc/sys/net/core/wmem_max 發送buffer最大大小,單位字節

對應內核參數:net.core.rmem_max, 能夠在 /etc/sysctl.conf 中進行修改;

注意:修改 /etc/sysctl.conf 以後,必須執行 sysctl -p 命令才能生效。

10.5  offload配置

能夠將一些網絡操做 offload 到網絡硬件來負責。

ethtool -k eth0 能夠查看當前的 offload 配置:

[root@localhost ~]# ethtool --show-offload eth0
Features for eth0:
rx-checksumming: on
tx-checksumming: on
        tx-checksum-ipv4: off
        tx-checksum-unneeded: off
        tx-checksum-ip-generic: on
        tx-checksum-ipv6: off
        tx-checksum-fcoe-crc: off [fixed]
        tx-checksum-sctp: off [fixed]
scatter-gather: on
        tx-scatter-gather: on
        tx-scatter-gather-fraglist: off [fixed]
tcp-segmentation-offload: on
        tx-tcp-segmentation: on
        tx-tcp-ecn-segmentation: off
        tx-tcp6-segmentation: off
udp-fragmentation-offload: off [fixed]
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off [fixed]
rx-vlan-offload: on [fixed]
tx-vlan-offload: on [fixed]
ntuple-filters: off [fixed]
receive-hashing: off [fixed]
highdma: off [fixed]
rx-vlan-filter: on [fixed]
vlan-challenged: off [fixed]
tx-lockless: off [fixed]
netns-local: off [fixed]
tx-gso-robust: off [fixed]
tx-fcoe-segmentation: off [fixed]
tx-gre-segmentation: off [fixed]
tx-udp_tnl-segmentation: off [fixed]
fcoe-mtu: off [fixed]
loopback: off [fixed]

ethtool -K eth0 rx on|off, ethtool -K eth0 tx on|off, ethtool -K eth0 tso on|off 進行修改

10.6  調大 接收隊列和發送隊列的大小:

1)接收隊列:/proc/sys/net/core/netdev_max_backlog 對應內核參數:net.core.netdev_max_backlog

2)發送隊列:

[root@localhost ~]# ifconfig eth0 | grep txqueue
          collisions:0 txqueuelen:1000

進行修改:ifconfig eth0 txqueuelen 20000

10.7  調大 SYN 半鏈接 tcp_max_syn_backlog 數量

TCP三次握手創建鏈接時,被動打開方,有一個狀態是SYN,

When the server is heavily loaded or has many clients with bad connections with high latency, it can result in an increase in half-open connections. This is common for Web servers, especially when there are a lot of dial-up users. These half-open connections are stored in the backlog connections queue. You should set this value to at least 4096. (The default is 1024.)
Setting this value is useful even if your server does not receive this kind of connection, because it can still be protected from a DoS (syn-flood) attack.

cat /proc/sys/net/ipv4/tcp_max_syn_backlog 對應內核參數: net.ipv4.tcp_max_syn_backlog,能夠在/etc/sysctl.conf文件中配置。

sysctl -w net.ipv4.tcp_max_syn_backlog=4096

當服務器負載很重時,會致使不少的客戶端的鏈接,服務器沒有進行確認,因此就處在 SYN 狀態,這就是所謂的半鏈接(half-open connection).半鏈接的數目由 tcp_max_syn_backlog 參數控制,增大它能夠避免客戶端的鏈接被拒絕,同時也能防護SYN洪水攻擊。也就是能夠容納更多的等待鏈接的數量。

10.8   /proc/sys/net/core/somaxconn 和 net.core.somaxconn 

該參數爲完成3次握手,已經創建了鏈接,等待被accept而後進行處理的數量。默認爲128,咱們能夠調整到 65535,甚至更大。也就是尅有容納更多的等待處理的鏈接。

相關文章
相關標籤/搜索