今天暴風雨襲擊了杭州,而昨天暴風雨(高並發問題)席卷了園子,留下一片狼藉。
在前天傍晚,我們進行了 .net core 版博客站點的第二次發布嘗試,在發布后通過 kestrel 直接監聽取代 nginx 轉發解決了高並發下的1秒延遲問題,成功地頂住了下班前的訪問小高峰,但這只是一場大雨,第二天的上午和下午的暴風雨(訪問高峰中的高並發)才是真正的考驗。
昨天,面對暴風雨,我們哼都不敢哼一聲“讓暴風雨來得更猛烈些吧”,只是一直不停地默念“讓暴風雨快點過去吧”,尤其在下午的暴風雨襲擊下,跑在 docker swarm 上 .net core 版博客系統潰不成軍,大量請求響應速度極不穩定,時而快如閃電(10ms左右),時而慢如蝸牛(10s, 30s 甚至超時)。與第一次發布時不一樣,不僅博客應用容器外是暴風雨,容器內也是暴風雨,在容器內用 curl 命令訪問與外部用瀏覽器訪問問題一樣(難不成真的是 docker swarm 網絡的問題?kestrel 監聽取代 nginx 轉發只是將網絡並發負載從 nginx 容器轉到了 kestrel 所在的博客應用容器。。。有待驗證。)
昨天 17:30 左右並發量回落到一定程度之后,暴風雨飄然而去,立刻風平浪靜,晴空萬里,下午的那場暴風雨宛如夢中。
在暴風雨過后,我們查看了服務器的 linux 系統日志,發現很多下面的日志,而且都發生在暴風雨期間。
Aug 8 15:57:12 blog-swarm-n3 kernel: nf_conntrack: table full, dropping packet Aug 8 15:57:12 blog-swarm-n3 kernel: nf_conntrack: table full, dropping packet Aug 8 15:57:12 blog-swarm-n3 kernel: nf_conntrack: table full, dropping packet
當時 docker swarm 集群中一共5台 worker 節點服務器,統計了一下每台服務器出現 "table full" 日志的數量。
blog-swarm-n3: 2149 blog-swarm-n4: 1964 blog-swarm-n5: 2451 blog-swarm-n6: 2095 blog-swarm-n7: 0
咦,怎么有1台服務器為0?哦,原來是這台沒有掛上所有負載均衡,只承受了 2/3 左右的流量,雖然下的暴風雨,但對這台服務器來說只是一場大雨。
針對上面的日志,我們調整了 linux 內核的 2 個設置置(參考文檔),在 /etc/sysctl.conf 中添加
net.netfilter.nf_conntrack_max = 655350 net.netfilter.nf_conntrack_tcp_timeout_established = 1200
這個調整成為我們今天唯一的希望,但早上訪問高峰來臨的時候,迎接我們的不是喜出望外,而是昔日重來。。。
在熟悉的暴風雨面前,我們面臨着艱難的選擇,放棄-退回 windows 上的 .net framework 版博客系統,還是堅持-至少要找到一種能抵擋一定程度暴風雨的臨時解決方法?
那台沒有 "table full" 日志的服務器給了我們啟發——分而治之,將暴風雨變成每一台服務器的大雨,拆分流量到不同的服務器,減少每台服器的並發連接數,今天就是通過這個臨時的笨方法扛住了暴風雨,大量減少了響應速度慢的情況,所以到現在 .net core 版博客站點依然在線。
在抗過今天上下午訪問高峰的暴風雨后,杭州也被暴風雨襲擊了,因為有了房子,任憑外面風吹雨打,我們可以坐在房間里一邊敲着代碼,一邊凝聽着窗外的風雨聲。對於這次遇到的高並發問題,我們相信總有一天會為我們的博客系統建造好房子,在暴風雨的風吹雨打中瀟灑地在日志中寫着“讓暴風雨來得更猛烈些吧”。