今天是三八國際婦女節, 也是中國農曆二月二/龍擡頭的節日,恭祝女同胞節日快樂!恭祝中國善良的人們都擡頭見喜!緩存
好一陣子沒更新Blog,今天也借這喜氣沖刷一下往日的陰霾,通過多日的觀察,終於找到這陣子「有福新聞」高負載多併發服務器的異常報錯背後的緣由之一。此前在Blog中頻繁觀測到 GWA2 PHP Memcached的報錯,而且在代碼層面進行了屢次調優,問題暫時獲得緩解,深層並未深究出個因此然。服務器
「GWA2 PHP Memcached自動追加服務器鏈接?一例緩存服務被擊穿的異常分析」, -R/52SP 。網絡
在進行平常服務器狀態巡檢時,先是發現 Apache 在很多天的持續運行中,會有 segmentation fault 致使的死掉,因而對 Apache 2.4.x 進行升級到最新版的操做,然而加了保護措施。儘管偶爾有 Apache child 有 segmentation fault退出,但整個服務頑強的活着.併發
後續幾日的連續觀測中,Apache暫無異常死掉,而 GWA2 PHP Memcached再次開始報錯,報錯信息爲惟一的 127.0.0.1/11211 服務被標記爲 DEAD (error code: 35). 然而在終端用 telnet 進行手工模擬時,memcached的服務又是正常的,這是爲什麼?時好時壞,隨機出錯嗎?app
近日繼續探測,在最近的一次服務器上嘗試使用 ping ufqi.com 時,命令行開始報錯說 sendmeg not permitted… 因而一例服務器操做系統層面的問題被曝露出來。ide
ping命令的沒法執行,多是網絡配置或操做系統異常,循着這個思路,咱們使用 journalctl -f 命令,很快看到 kernel層的報錯信息:memcached
Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet
Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet
Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet優化
原來是系統的網絡鏈接池出現了問題!關於 「nf_conntrack: table full, dropping packet」 這裏 -R/u2SR 有詳細的解釋。 簡單地說,操做系統集成了 Netfilter 防火牆服務,基於 iptables 的操做系統的鏈接管理器中,有四個 table(表) 和五個 chain(鏈)。操作系統
Fig1. Iptables 4 tables and 5 chains.net
Tables: categorized by different operations to data packets.
raw
: highest priority, only appied toPREROUTING
andOUTPUT
chain. When we don’t need to do NAT, we can use RAW table to increase performance.
mangle
: modify certain data packet
nat
: NAT, port mapping, address mapping
filter
: filterChains: categorized by different hooks.
PREROUTING
: packet before going to route table
INPUT
: after packet passing route table, destination is current machine
FORWARDING
: after packet passing route table, destination is not current machine
OUTPUT
: packet comes from current machine and to outside
POSTROUTIONG
: packet before going to network interface
當操做系統處理 TCP/IP 鏈接相關模塊出錯時,全部基於鏈接的服務都會報出異常。這是此前在代碼層不管如何優化都沒辦法解決OSI分層中更底層的問題。
操做系統默認的併發鏈接數爲 65535, 經過命令:cat /proc/sys/net/netfilter/nf_conntrack_max 能夠查看到。 若是經過命令 cat /proc/sys/net/netfilter/nf_conntrack_count 得到到的數字等於 max 的最大值時,此時再有新建立鏈接的需求就會報錯,當建立鏈接失敗時,基於其上的全部應用都將失敗,而這些在代碼層並不容易解決。推薦的 /proc/sys/net/netfilter/nf_conntrack_max 值的計算公式: CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32) , 如 8GB RAM in x86_64 OS, max = 8*1024^3/16384/2=262144 。
當一臺繁忙的服務器的鏈接數超過默認值時,須要經過修改 /proc/sys/net/netfilter/nf_conntrack_max 來使得系統可以接收更多鏈接進來。
臨時修改:
echo 524288 > /proc/sys/net/netfilter/nf_conntrack_max
or
sysctl -w net.netfilter.nf_conntrack_max=262144
永久修改:
在 /etc/rc.d/after.local 或者 /etc/rc.d/rc.local 中增長上述命令行語句。
除了增長 /proc/sys/net/netfilter/nf_conntrack_max 參數設定外,還能夠經過調整 iptables 的表或者鏈上相關規則來進行調優,更多參考: -R/u2SR 。
「有福新聞」, 「全國招投標信息中心」 等服務又能夠暢快地運行並有信心地迎接下一次洪峯的到來。
小結:
1. 在代碼層很難發現操做系統層的問題,可行的路線是分析應用層源碼;
2. 系統層的異常,經過具備隨機性,好比鏈接數,是一個動態變化數據,可能下一秒異常就沒有了,沒法肯定重現的問題爲 troubleshooting 帶來了必定的障礙。
可是,已有的問題,在沒解決以前,會再次發生,這是肯定的。