日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

瞬发大量并发连接 造成MySQL连接不响应的分析

發(fā)布時間:2025/3/21 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 瞬发大量并发连接 造成MySQL连接不响应的分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://www.actionsky.com/docs/archives/252

?2016年12月7日

目錄

  • 1?現(xiàn)象
  • 2?猜想
  • 3?檢查環(huán)境
  • 4?猜想2
  • 5?分析
    • 5.1?TCP握手的第三步ACK包為什么丟失
  • 6?恢復故障與日志的正關聯(lián)
  • 7?解決方案

現(xiàn)象

Sysbench對MySQL進行壓測, 并發(fā)數(shù)過大(>5k)時, Sysbench建立連接的步驟會超時.

猜想

猜想: 直覺上這很簡單, Sysbench每建立一個連接, 都要消耗一個線程, 資源消耗過大導致超時.

驗證: 修改Sysbench源碼, 調大超時時間, 仍然會發(fā)生超時.

檢查環(huán)境

猜想失敗, 回到常規(guī)的環(huán)境檢查:

  • MySQL error log 未見異常.
  • syslog 未見異常.
  • tcpdump 觀察網(wǎng)絡包未見異常, 連接能完成正常的三次握手; 只觀察到在出問題的連接中, 有一部分的TCP握手的第一個SYN包發(fā)生了重傳, 另一部分沒有發(fā)生重傳.
  • 自己寫一個簡單的并發(fā)發(fā)生器, 替換sysbench, 可重現(xiàn)場景. 排除sysbench的影響
  • 猜想2

    懷疑 MySQL 在應用層因為某種原因, 沒有發(fā)送握手包, 比如卡在某一個流程上:

  • 檢查MySQL堆棧未見異常, 仿佛MySQL在應用層沒有看到新連接進入.
  • 通過strace檢查MySQL, 發(fā)現(xiàn)accept()調用確實沒有感知到新連接.
  • 懷疑是OS的原因, Google之, 得到參考文檔:?A TCP “stuck” connection mystery

    分析

    參考文檔中的現(xiàn)象跟目前的狀況很類似, 簡述如下:

    正常的TCP連接流程:

  • Client 向 Server 發(fā)起連接請求, 發(fā)送SYN.
  • Server 預留連接資源, 向 Client 回復SYN-ACK.
  • Client 向 Server 回復ACK.
  • Server 收到 ACK, 連接建立.
  • 在業(yè)務層上, Client和Server間進行通訊.
  • 當發(fā)生類似SYN-flood的現(xiàn)象時, TCP連接的流程會使用SYN-cookie, 變?yōu)?

  • Client 向 Server 發(fā)起連接請求, 發(fā)送SYN.
  • Server 不預留連接資源, 向 Client 回復SYN-ACK, 包中附帶有簽名A.
  • Client 向 Server 回復ACK, 附帶 f(簽名A) (對簽名進行運算的結果).
  • Server 驗證簽名, 分配連接資源, 連接建立.
  • 在業(yè)務層上, Client和Server間進行通訊.
  • 當啟用SYN-cookie時, 第3步的ACK包因為?某種原因?丟失, 那么:

  • 從Client的視角, 連接已經(jīng)建立.
  • 從Server的視角, 連接并不存在, 既沒有建立, 也沒有”即將建立” (若不啟用SYN-cookie, Server會知道某個連接”即將建立”)
  • 發(fā)生這種情況時:

  • 若業(yè)務層的第一個包應是從 Client 發(fā)往 Server, 則會進行重發(fā)或拋出連接錯誤
  • 若業(yè)務層的第一個包應是從 Server 發(fā)往 Client的, Server不會發(fā)出第一個包. MySQL的故障就屬于這種情況.
  • TCP握手的第三步ACK包為什么丟失

    參考文檔中, 對于TCP握手的第三步ACK包的丟失原因, 描述為:

    Some of these packets get lost because some buffer somewhere overflows.

    我們可以通過Systemtap進一步探究原因. 通過一個簡單的腳本:

    probe kernel.function("cookie_v4_check").return {source_port = @cast($skb->head + $skb->transport_header, "struct tcphdr")->sourceprintf("source=%d, return=%d\n", readable_port(source_port), $return) }function readable_port(port) {return (port & ((1<<9)-1)) << 8 | (port >> 8) }

    觀察結果, 可以確認cookie_v4_check?(syn cookie機制進行包簽名檢查的函數(shù))會返回 NULL(0). 即驗證是由于syn cookie驗證不通過, 導致TCP握手的第三步ACK包不被接受.

    之后就是對其中不同條件進行觀察, 看看是哪個條件不通過. 最終原因是accept隊列滿 (sk_acceptq_is_full):

    796 static inline bool sk_acceptq_is_full(const struct sock *sk) 797 { 798 return sk->sk_ack_backlog > sk->sk_max_ack_backlog; 799 }

    恢復故障與日志的正關聯(lián)

    在故障處理的一開始, 我們就檢查了syslog, 結論是未見異常.

    當整個故障分析完成, 得知了故障與syn cookie有關, 回頭看syslog, 里面是有相關的信息, 只是和故障發(fā)生的時間不匹配, 沒有正關聯(lián), 因此被忽略.

    檢查Linux源碼:

    6130 if (!queue->synflood_warned && 6131 sysctl_tcp_syncookies != 2 && 6132 xchg(&queue->synflood_warned, 1) == 0) 6133 pr_info("%s: Possible SYN flooding on port %d. %s. Check SNMP counters.\n", 6134 proto, ntohs(tcp_hdr(skb)->dest), msg);

    可以看到日志受到了抑制, 因此日志與故障的正關聯(lián)被破壞.

    粗看源碼, 每個listen socket只會發(fā)送一次告警日志, 要獲得日志與故障的正關聯(lián), 必須每次測試重啟MySQL.

    解決方案

    這種故障一旦形成, 難以檢測; 系統(tǒng)日志中只會出現(xiàn)一次, 在下次重啟MySQL之前就不會再出現(xiàn)了; Client如果沒有合適的超時機制, 萬劫不復.

    解決方案:
    1. 修改MySQL的協(xié)議, 讓Client先發(fā)握手包. 顯然不現(xiàn)實.
    2. 關閉syn_cookie. 有安全的人又要跳出來了.
    3. 或者調高syn_cookie的觸發(fā)條件 (syn backlog長度). 降低系統(tǒng)對syn flood的敏感度, 使之可以容忍業(yè)務的syn波動.

    有多個系統(tǒng)參數(shù)混合影響syn backlog長度, 參看http://blog.dubbelboer.com/2012/04/09/syn-cookies.html?

    總結

    以上是生活随笔為你收集整理的瞬发大量并发连接 造成MySQL连接不响应的分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。