天天看點

TCP: too many of orphaned sockets報錯解決

在服務端,連接配接達到一定數量,諸如50W時,有些隐藏很深的問題,就不斷的抛出來。 通過檢視dmesg指令檢視,發現大量TCP: too many of orphaned sockets錯誤,也很正常,下面到了需要調整tcp socket參數的時候了。

第一個需要調整的是tcp_rmem,即TCP讀取緩沖區,機關為位元組,檢視預設值

預設值為87380 byte ≈ 86K,最小為4096 byte=4K,最大值為4064K。

第二個需要調整的是tcp_wmem,發送緩沖區,機關是位元組,預設值

解釋同上

第三個需要調整的tcp_mem,調整TCP的記憶體大小,其機關是頁,1頁等于4096位元組。系統預設值:

tcp_mem(3個INTEGER變量):low, pressure, high

low:當TCP使用了低于該值的記憶體頁面數時,TCP不會考慮釋放記憶體。

pressure:當TCP使用了超過該值的記憶體頁面數量時,TCP試圖穩定其記憶體使用,進入pressure模式,當記憶體消耗低于low值時則退出pressure狀态。

high:允許所有tcp sockets用于排隊緩沖資料報的頁面量,當記憶體占用超過此值,系統拒絕配置設定socket,背景日志輸出“TCP: too many of orphaned sockets”。

一般情況下這些值是在系統啟動時根據系統記憶體數量計算得到的。 根據目前tcp_mem最大記憶體頁面數是1864896,當記憶體為(1864896*4)/1024K=7284.75M時,系統将無法為新的socket連接配接配置設定記憶體,即TCP連接配接将被拒絕。

實際測試環境中,據觀察大概在99萬個連接配接左右的時候(零頭不算),程序被殺死,觸發out of socket memory錯誤(dmesg指令檢視獲得)。每一個連接配接大緻占用7.5K記憶體(下面給出計算方式),大緻可算的此時記憶體占用情況(990000 * 7.5 / 1024K = 7251M)。

這樣和tcp_mem最大頁面值數量比較吻合,是以此值也需要修改。

三個TCP調整語句為:

備注: 為了節省記憶體,設定tcp讀、寫緩沖區都為4K大小,<code>tcp_mem</code>三個值分别為3G 8G 16G,<code>tcp_rmem</code>和<code>tcp_wmem</code>最大值也是16G。

經過若幹次的嘗試,最終達到目标,1024000個持久連接配接。1024000數字是怎麼得來的呢,兩台實體機器各自發出64000個請求,兩個配置為6G左右的centos測試端機器(綁定7個橋接或NAT連接配接)各自發出640007 = 448000。也就是 1024000 = (64000) + (64000) + (640007) + (64000*7), 共使用了16個網卡(實體網卡+虛拟網卡)。 

終端輸出

線上使用者目标達到1024000個!

服務啟動時記憶體占用:

<code>                 total       used       free     shared    buffers     cached     Mem:         10442        271      10171          0         22         78     -/+ buffers/cache:        171      10271     Swap:         8127          0       8127</code>

<code></code>

系統達到1024000個連接配接後的記憶體情況(執行三次 free -m 指令,擷取三次結果):

<code>                 total       used       free     shared    buffers     cached     Mem:         10442       7781       2661          0         22         78     -/+ buffers/cache:       7680       2762     Swap:         8127          0       8127                  total       used       free     shared    buffers     cached     Mem:         10442       7793       2649          0         22         78     -/+ buffers/cache:       7692       2750     Swap:         8127          0       8127                  total       used       free     shared    buffers     cached     Mem:         10442       7804       2638          0         22         79     -/+ buffers/cache:       7702       2740     Swap:         8127          0       8127</code>

這三次記憶體使用分别是7680,7692,7702,這次不取平均值,取一個中等偏上的值,定為7701M。那麼程式接收1024000個連接配接,共消耗了 7701M-171M = 7530M記憶體, 7530M*1024K / 1024000 = 7.53K, 每一個連接配接消耗記憶體在為7.5K左右,這和在連接配接達到512000時所計算較為吻合。 

虛拟機運作Centos記憶體占用,不太穩定,但一般相差不大,以上數值,僅供參考。

執行top -p 某刻輸出資訊:

<code>    Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie     Cpu(s):  0.2%us,  6.3%sy,  0.0%ni, 80.2%id,  0.0%wa,  4.5%hi,  8.8%si,  0.0%st     Mem:  10693580k total,  6479980k used,  4213600k free,    22916k buffers     Swap:  8323056k total,        0k used,  8323056k free,    80360k cached       PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                            2924 yongboy   20   0 82776  74m  508 R 51.3  0.7   3:53.95 server </code>

執行vmstate:

擷取目前socket連接配接狀态統計資訊:

擷取目前系統打開的檔案句柄:

此時任何類似于下面查詢操作都是一個慢,等待若幹時間還不見得執行完畢。

以上兩個指令在二三十分鐘過去了,還未執行完畢,隻好停止。

本次從頭到尾的測試,所需要有的linux系統需要調整的參數也就是那麼幾個,彙總一下:

<code>     echo "* - nofile 1048576" &gt;&gt; /etc/security/limits.conf     echo "fs.file-max = 1048576" &gt;&gt; /etc/sysctl.conf     echo "net.ipv4.ip_local_port_range = 1024 65535" &gt;&gt; /etc/sysctl.conf     echo "net.ipv4.tcp_mem = 786432 2097152 3145728" &gt;&gt; /etc/sysctl.conf     echo "net.ipv4.tcp_rmem = 4096 4096 16777216" &gt;&gt; /etc/sysctl.conf     echo "net.ipv4.tcp_wmem = 4096 4096 16777216" &gt;&gt; /etc/sysctl.conf</code>

其它沒有調整的參數,僅僅因為它們暫時對本次測試沒有帶來什麼影響,實際環境中需要結合需要調整類似于SO_KEEPALIVE、tcpmax_orphans等大量參數。

本文轉自    憬薇   51CTO部落格,原文連結:http://blog.51cto.com/welcomeweb/1975364

繼續閱讀