文章出處

SQL Server 連接問題案例解析(1)


   Microsoft Network Monitor(Netmon)是由微軟發布的一款網絡協議數據分析工具,利用Netmon可以捕獲網絡數據并進行查看和分析。
在處理SQL Server 的連接問題時,Netmon常常會起到關鍵的作用。在本篇博文中,我將為大家分享一個通過使用 Netmon 解決的經典案例。
      在這個案例中,客戶發現在客戶端的 SQL Server Management Studio 中執行某一個Query時就會發生錯誤,
錯誤信息是“connection forcibly close by the remote server ”。
 
為了調查連接被關閉的原因,我們在客戶端和服務端抓取了Netmon。在正式分析這個案例前,我們先來介紹一些有關Netmon的知識和使用技巧。
 
                                                     Netmon界面

1. 在Netmon界面中的Frame Summary 部分,我們首先可以看到Frame Number,不管我們在瀏覽時是否有設置filter,Frame Number的值是不會發生改變的,
它相當于Frame的一個行號。
 
2. 在左側Network Conversation 中,我們會看到進程的name和ID,在示例中即為Ssms.exe和3352。繼續展開后看到IPv4,
那么我們可以知道這個conversation是從哪里來的。再次展開可以看到這個conversation的端口,本示例中,端口為143349428
 
在這里需要額外講解一下,當客戶端程序創建連接到SQL Server時會使用哪些端口呢?
客戶端會向操作系統申請并使用一個動態端口并向SQL Server發送連接請求。如果在連接時使用的是machine name,provider默認會去連接1433端口,
這是一個provider的行為,改變這個行為需要修改注冊表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\<Provider>\tcp\DefaultPort

3. 當客戶端嘗試創建一個連接到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,

6. 除了在4中介紹的通過port進行過濾,最常用的filter還有
ipv4.address==<xxx.xx.xx.xx>
除直接在filter中寫入之外還有一種添加filter的方法,以過濾出所有flag是reset的frames為例來說明:那么我可以在某個reset frame的details中找到這個flag,
在右鍵單擊彈出的菜單中選擇Add Selected
Value 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)。

 

 

 


     
   開啟Jumbo Packet表示支持大包,關閉則表示從NIC發出的包采用標準大小1500。

      如果LSO是開啟的,切包會由網卡驅動(NDIS)完成。如果LSO關閉,切包會由操作系統(TCP Stack)完成,切成多大由Jombo Packet的設置來決定。
我們通常不建議由網卡來切包,因為網卡切包與網絡環境有關,可能會導致包的大小不固定,建議還是由操作系統來進行切包。
將這兩個選項關閉后,傳輸包的大小均為標準大小1500,就解決了這個大包被切,重傳失敗的問題。

      這就是今天的分享,更多SQL Server案例學習請持續關注本博客的更新。

server端Netmon和client端netmon
 
Jumbo Packet:巨型包
 

文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()