【20180607】關於TCP隊列信息溢出的排查和解釋

關於TCP隊列問題和內核參數的優化

http請求或者https請求間歇性的被丟棄或者訪問失敗的排查流程
  1. 檢查dev 和網卡設備層,是否有error和drop。硬件和系統層面錯誤。

    • cat /proc/net/dev
      • errors:由設備驅動程序檢測到的發送或者接受錯誤的總數
      • drop:設備驅動程序丟棄包總數
    • ifconfig
  2. 觀察socket overflow 和 socket droped。如果應用處理全連接隊列(accept queue)過慢則會導致socket overflow,影響半連接隊列(syn queue)溢出而導致socket dropped

    • netstat -s | grep -i listen
      • 645870725 times the listen queue of a socket overflowed
      • 645990109 SYNs to LISTEN sockets ignored
      • 隔段時間查看或者說監控SYN socket overflow和socket droped急劇增加的話則說明,TCP的三次握手是存在很大的問題的。
    • 關於TCP三次握手的。
      • client發送syn給server端。
      • server接收到client的syn,這個時候則會將相關信息放到半鏈接隊列(syn queue),並且發送syn+ack發送給client。
      • client接受到server的syn+ack之後,發送一個ack給server告訴server我接收到了。這個時候server就會將相關信息放到全連接隊列(accept queue)中。
  3. 檢查sysctl內核參數。

    • 內核參數詳解sysctl -a
      • fs.file-max:設置系統所有進程一共可以打開的文件數量。和ulimit的區別就是,ulimit設置的是當前shell以及由它啓動的進程的資源限制。
      • net.core.somaxconn:表示socket監聽(listen)的backlog的上限,即全連接隊列上限(accept queue)。backlog就是socket的監聽隊列,當一個請求(request)尚未被處理或建立時,它會進入backlog。而socket server可以一次性處理backlog中的所有請求,處理後的請求不在位於監聽隊列中。當server處理請求比較慢,以至於監聽隊列被填滿後,新的請求會被拒絕。
      • net.core.netdev_max_backlog:在每個網絡接口接收數據包的速率比內核處理這些數據包快的時候,允許送到隊列的數據包的最大數目。
      • net.ipv4.tcp_max_syn_backlog:指定所能接受SYN同步包的最大客戶端數量,即半連接隊列(syn queue)上限
      • net.ipv4.tcp_syncookies=1:表示開啓SYN Cookies。當出現SYN等待隊列溢出的時候,啓用cookies來處理少量的SYN×××。
      • net.ipv4.tcp_tw_reuse=1:表示開啓tcp連接重用。表示允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉。
      • net.ipv4.tcp_tw_recycle=1:表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。若是過NAT,則需要禁用這個參數。因爲當同時在server端開啓tcp_timestamps和recycle的時候,60s內同一源IP主機的socket connect請求中的timestamp必須是遞增的。
      • net.ipv4.tcp_timestamps:TCP時間戳(會在TCP包頭增加12個字節)。
    • ss -lnt查詢。主要針對的是基於應用或者短褲的半鏈接當前值和全連接的上限值。
      • Recv-Q:表示的是當前等待server端調用accept完成三次握手的listen backlog數值,也就是說,當客戶端發送syn給server端,server端接收到syn存放的半連接隊列(SYN queue)的當前值。
      • Send-Q:表示全連接隊列(accept queue)上限的數值,min(backlog,somaxconn)的值。
  4. 檢查selinux和NetworkManager是否啓用,禁用狀態。
  5. 抓包判斷請求進來後應用處理的情況,是否收到SYN未響應的情況。
驗證
  1. 查看全連接隊列(accept queue)溢出之後,OS處理設置:
    • cat /proc/sys/net/ipv4/tcp_abort_on_overflow
      • 0:表示如果三次握手第三步的時候全連接隊列滿了那麼server扔掉client發過來的ack(在server端則會認爲連接沒有建立起來)
      • 1:表示如果三次握手第三步的時候全連接隊列滿了,server端就會發送一個reset包給client端,表示廢棄這個握手過程和這個鏈接。(在server端也會認爲連接沒有建立起來)
  2. 設置tcp_abort_on_overflow爲1
    • echo 1 > /proc/sys/net/ipv4/tcp_abort_on_overflow
  3. 查看server端的web服務是否存在許多的connection reset peer錯誤。
  4. 查看sysctl -a內核參數 backlog,somaxconn,file-max和nginx的blocklog參數。
  5. ss -lnt查看服務的Send-Q全隊列的上限和Recv-Q的當前半鏈接的值。
  6. 內核參數優化:
    • net.ipv4.tcp_syncookies = 1
    • net.ipv4.tcp_max_syn_backlog = 16384
    • net.core.somaxconn = 16384
      • 最大極限值是65535。當超過了這個值的話需要轉化爲二進制,區最後16位,再轉化爲10進制。
  7. nginx參數優化
    • backlog = 32768
補充: SYN Flood洪水×××

當前最流行的DoS(拒絕服務×××)與DDos(分佈式拒絕服務×××)的方式之一,這是一種利用TCP協議缺陷,導致被×××服務器保持大量的SYN_RECV狀態的“半鏈接”,並且會重試默認的5次迴應第二個握手包,塞滿TCP等待連接隊列,耗盡資源(CPU滿負載或內存不足),讓正常的業務請求連接不進來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章