
Netmon界面1. 在Netmon界面中的Frame Summary 部分,我們首先可以看到Frame Number,不管我們在瀏覽時是否有設置filter,Frame Number的值是不會發生改變的,它相當于Frame的一個行號。2. 在左側Network Conversation 中,我們會看到進程的name和ID,在示例中即為Ssms.exe和3352。繼續展開后看到ipv4,那么我們可以知道這個conversation是從哪里來的。再次展開可以看到這個conversation的端口,本示例中,端口為1433到49428 。在這里需要額外講解一下,當客戶端程序創建連接到SQL Server時會使用哪些端口呢?客戶端會向操作系統申請并使用一個動態端口并向SQL Server發送連接請求。如果在連接時使用的是machine name,PRovider默認會去連接1433端口,這是一個provider的行為,改變這個行為需要修改注冊表:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/Client/<Provider>/tcp/DefaultPort3. 當客戶端嘗試創建一個連接到SQL Server,有了source port和destination port后,在這兩個port中就會形成一組physical tcp連接。形成連接之后每發一個包,包的sequence值就會發生變化。請注意,只有在同一個物理連接中,sequence的變化是連續的。如果客戶端和SQL Server建立了兩個不同的物理連接,這兩個連接中的sequence沒有任何關系。4. Netmon中數據量很大,如果查看呢?比如在瀏覽一個比較大的Netmon時,我們發現了一個Reset Flag:21 3:46:20 PM 9/5/2014 21.8000442 Ssms.exe 172.22.204.237 172.16.221.38 TCP TCP: [Bad CheckSum]Flags=...A.R.., SrcPort=49428, DstPort=1433, PayloadLen=0,Seq=3636257929, Ack=707503184, Win=0 {TCP:2,IPv4:1}就可以從這個Frame的詳細信息入手。從詳細信息中可以找到它的source port是49428。(1)此時我們可以就通過添加 filterTcp.port==49428 來過濾出這個Reset的conversation。(2)另外一種過濾方法是直接在右鍵單擊Frame后彈出的菜單中選擇Find Conversation, 但這種方法有可能會造成丟包,因此還是推薦使用第一種方法。找到了port就幾乎相當于找到了出問題的連接。當然,對于不同時間點,同樣的port有可能會是兩個不同的連接,因為上一個連接關掉后,下一個連接有可能重用這個port。按照port過濾后,從reset 開始順序往前看。5. 在Netmon中我們還可以看到一些protocol是TDS的Frame。TDS的好處是在查看Frame Details時,可以看到更多的信息。例如我們查看一個TDS:SQLBatch的TDS Frame Detail,可以看到SQL的statement:
對于當SQL Server使用的端口不是默認的1433時,如何顯示TDS frames,可以參考下面這篇博文:How to enable TDS parser to display TDS frames when SQLServer is listening on port other than default 14336. 除了在4中介紹的通過port進行過濾,最常用的filter還有ipv4.address==<xxx.xx.xx.xx>除直接在filter中寫入之外還有一種添加filter的方法,以過濾出所有flag是reset的frames為例來說明:那么我可以在某個reset frame的details中找到這個flag,在右鍵單擊彈出的菜單中選擇Add SelectedValue to Display filter:
7. 一個SQL Server的包會在網絡傳輸過程中會經過以下幾層:NIC(網卡物理設備)—》NDIS(網卡驅動)—》TCPIP (操作系統)—》afd(操作系統后臺線程,每一個tcp port上都會有一個afd)—》SQL Server—》for authentication(調用 sspi—lssas—DC)Netmon所抓取的數據是在網卡驅動上面和TCPIP 下面的。所以Netmon所抓到的包是不能作為網卡真正發出去的包的,需要比較發出去的包和客戶端收到的包來判斷網卡或路由等是否進行了切包。8. 在chimney開啟時,抓到的包的信息有可能是不全的,如果在查看時發現包的行為很奇怪,懷疑丟包,那么一定要請客戶關閉chimney(以管理員運行CMD并且執行命令:netsh interface tcp set global chimney=disabled)后重新收集Netmon。 接下來,我們就來討論一下今天的案例。當具備了以上Netmon的知識和技巧后,在處理這個案例中所收到的Netmon數據就非常有針對性了。將客戶端的Netmon數據按照端口號filter后,可以很清楚的看到,客戶端一直面對著重傳的問題。16是12的重傳,17也是12的重傳,甚至18,19,20:
那么我們來看一下12的詳細信息:
可以看到這個包的長度是4096。那么16呢?查看16的詳細信息時我們發現,16的長度變成了1460:
在重傳時包的長度變小說明,由于之前大包無法傳遞,傳遞的包的大小被自動調小了。繼續查看17,18,19和20會發現這幾個包的長度都是1460。很明顯,這是一個大包發不過去導致重傳的問題。 那么現在問題來了,為什么第一次大包發不過去,之后以小包重傳也不成功呢? 查看server端Netmon后會發現,這是由于傳輸4096的包被切成1460+1460+1172后,server端只收到了最后一個包。接下來,由于sequence斷了,server端會認為這是一個不合法的包,因為中間的信息缺失了。之后這個連接就在server端直接被block了(所以我們收到的錯誤信息是“connection forcibly close by the remote server”),因此后續re-transmit的1460的包server再也沒有接收過(后續重傳全都失敗了)。 最終問題的解決辦法是關閉網卡上的兩個選項:Jumbo Packet和Large Send Offload(LSO)。



新聞熱點
疑難解答