1. 程式人生 > 實用技巧 >Memcached 的惹禍,.NET 5.0 的背鍋

Memcached 的惹禍,.NET 5.0 的背鍋

抱歉,拖到現在才寫這篇為 .NET 5.0 洗白的博文(之前的博文),不好意思,又錯了,不是洗白,是還 .NET 5.0 的清白。

抱歉,就在今天上午寫這篇部落格的過程中,由於一個bug被迫在訪問高峰釋出,在10:30~11:10再次引發上次遇到的同樣故障,由此給您帶來麻煩,請您諒解。

2020年10月14日晚上我們釋出了升級至 .NET 5.0 RC 2 的部落格系統,在正式版釋出之前進行升級不是我們想追求前衛,而是因為:

  1. 微軟官博已經說明可以用於生產環境

RC2 is a “go live” release; you are supported using it in production.

  1. 正則表示式效能大幅提升(
    Regular expression performance improvements

On many of the expressions we’ve tried, these improvements routinely result in throughput improvements of 3-6x, and in some cases, much more.

  1. Json 序列化效能提升

JsonSerializer performance is significantly improved in .NET 5.0.

  1. 想使用 EF Core 5.0 的新特性(What's New in EF Core 5.0

最吸引我們的是第2點,部落格系統的程式碼中用了很多正則表示式,是耗CPU大戶。

而且升級很簡單:

  • TargetFramework 由 netcoreapp3.1 改為 net5.0
  • 更新 nuget 包
  • 容器映象 mcr.microsoft.com/dotnet/core/sdk:3.1 改為 mcr.microsoft.com/dotnet/sdk:5.0mcr.microsoft.com/dotnet/core/aspnet:3.1 改為 mcr.microsoft.com/dotnet/aspnet:5.0

釋出後從第2天上午訪問高峰的監控資料看,CPU消耗降了10%,效果不錯。

輕鬆升級,提前享受 .NET 5.0 的效能提升,印象中這是我們在 .NET Core 大版本升級歷史中最愜意的一次。

下午我們帶著升級後的喜悅心情歡迎新人的加入,現在能夠遇到有興趣學習 .NET 的新人也是不容易的,好了,現在可以直接學 .NET 5.0 了。就在新人歡迎會期間,網站出現了故障,昨晚升級到 .NET 5.0,今天下午就出故障,最大的嫌疑物件顯然是 .NET 5.0,當機立斷地進行回退操作,如果回退到升級之前的版本能恢復正常,那 .NET 5.0 就罪責難逃。

用下面的指令碼在k8s叢集上將部署回退到升級之前的容器映象

./deploy-blog.sh 2.3.73 

回退完成之後,很快恢復正常,鐵證如山,隨後我們立即發博宣判——部落格系統升級到 .NET 5.0 引發的故障,讓還未正式出茅廬的 .NET 5.0 就背上一口沉重的鍋。

幸好有開發同事沒有這麼片面地看待問題,對故障進行了進一步分析,發現故障與 memcached 伺服器的 tcp 連線數異常高有關,大量的資料庫連線超時是因為連不上 memcached (達到了1萬的最大連線數限制)造成大量請求直接訪問資料庫引起的。更進一步地,還找到了重現問題的方法,多次點選某些部落格,就能讓 memcached tcp 連線數飆升,排查後發現這些部落格需要被快取的資料超過了1M,超出了 memcached 單個快取項的大小限制(預設就是1M),造成資料永遠無法被快取,但每次都要徒勞地讀寫 memcached 伺服器。我們針對這個問題進行了修復,修復後重新發布了 .NET 5.0 版,觀察幾天後沒有再次出現故障。

我們錯怪了 .NET 5.0,我們的一時武斷讓 .NET 5.0 在即將出道之前先背鍋,我們向 .NET 5.0 說抱歉,向被誤導的 .NET 開發者說抱歉,我們會吸取教訓,在故障發生後不要急於發博文,先全面分析問題,不能因為我們的一時誤判產生誤導。

雖然修復了問題,用上了 .NET 5.0,但問題背後的真正原因至今沒有弄明白——僅僅幾次滑鼠點選,快取資料超過1M,就能讓 memcached 伺服器的 tcp 連線數飆升?可能與我們使用的 memcached 客戶端 EnyimMemcachedCore,待以後再找時間研究。

今天在寫這篇博文的期間,再次遇到這個故障,看來有緣分,想躲也躲不過去了。今天發生故障與訪問高峰釋出有關,但之前我們評估過訪問高峰釋出的影響,也就5-10分鐘左右訪問速度變慢,不會產生如此大的重創。這次故障與上次是同樣的表現,memcached tcp 連線數異常高,頻頻達到1萬的最大連線數限制,開啟網頁速度慢就是因為在等待與 memcached 伺服器建立 tcp 連線,重啟 memcaced 於事無補,很快就會再次飆升至1萬,平時訪問高峰也就5000左右的連線。

從 memcached 伺服器的其他指標看,雖然上萬的 tcp 連線,但並沒有不堪重負,難道僅僅是車多路窄造成的堵車引起大家都通行緩慢?那把路拓寬不就行了,於是將 memcached 伺服器的 tcp 最大連線數限制由1萬拓寬到2萬,本擔心連線數會飆升到2萬,但沒想到竟然恢復正常了。可能是某種特殊情況造成需要稍過萬的 tcp 連線,但最大連線數限制把大家都堵住了,看來程式碼世界也最怕堵車。

今天集中3個多小時的時間才完成這篇粗糙的博文,在故障後分享一篇博文也不是一件容易的事。