今天我們分析了部落格站點的2次故障(故障一、故障二),發現一個巧合的地方,.NET 5.0 正式版的 docker 映象是在11月10日提前釋出上線的。
而在11月10日下午4點左右,由於 CI 伺服器磁碟空間用完,我們進行了磁碟清理,刪除了 CI 伺服器上的所有映象,清理之前 CI 伺服器上 .NET 5.0 映象版本對應的是 .NET 5.0 RC 2,所以11月10日晚上釋出部落格站點時,CI 伺服器重新下載了映象,這時正好下載了 .NET 5.0 正式版的 docker 映象,所以釋出時部落格系統的映象是基於 .NET 5.0 正式版(釋出時會在CI伺服器上生成應用的生產環境映象)。
現在可以進入這2個釋出版本的映象進行驗證
$ docker run -t blog-web:2.3.101 dotnet --info Host (useful for support): Version: 5.0.0 Commit: cf258a14b7 $ docker run -t blog-web:2.3.102 dotnet --info Host (useful for support): Version: 5.0.0 Commit: cf258a14b7
Commit: cf258a14b7 對應的正是 .NET 5.0 正式版。
對比一下11月10日之前生成的映象
$ docker run -t blog-web:2.3.100 dotnet --info Host (useful for support): Version: 5.0.0-rc.2.20475.5 Commit: c5a3f49c88
不僅 Commit 不一樣,而且 Version 中包含 rc.2。
所以這2次故障時用的都是基於 .NET 5.0 正式版的映象,而且11月10日至11月12日期間,我們只進行了2次釋出,2次都出現了故障。
如果片面地從這個巧合來看,似乎故障與 .NET 5.0 正式版映象有關,這時你可能立馬提出疑問,同樣是基於 .NET 5.0 正式版的映象,為什麼今天早上釋出沒有出現故障?
根據我們的分析判斷,故障的觸發與釋出時的併發請求量有關,2次故障時的釋出時間分別是在 20:30 與 19:30 左右,這2個釋出時間點的併發量差不多,而今天早上釋出時併發量要小很多,而且我們其他併發量不大的應用升級到 .NET 5.0 沒有出現過這個問題,所以今天早上釋出正常很可能是因為沒有到達觸發故障的併發量。
另外,今天早上釋出時我們已經將部落格專案依賴的下面這些 nuget 包升級到 .NET 5.0 正式版對應的版本,昨天晚上在處理故障時也進行過這個升級釋出嘗試,但沒有解決問題,與故障關聯的可能性很小,但從中可以得到的資訊是故障時專案程式碼是基於 .NET 5.0 RC 2,生產環境部署的 runtime 是基於 .NET 5.0 正式版。
Microsoft.Extensions.Primitives System.Interactive.Async Microsoft.Extensions.Http Microsoft.Extensions.Logging.Abstractions System.ServiceModel.Primitives Microsoft.EntityFrameworkCore.SqlServer Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation System.Text.Encoding.CodePages
雖然正式版 runtime 映象造成這個故障的可能性很小,但考慮到問題的詭異性,我們不想放過一個蛛絲馬跡,所以準備今天晚上再次釋出試試,計劃的釋出時間是21:30,但是由於今天是週五,晚上的併發請求量比前2次故障期間小一些,即使沒有出現問題,也不能說明100%沒問題,但至少可以知道在週五晚上的併發量下不會觸發問題。
【更新】這次釋出沒有出現故障,下圖是 memcached 伺服器 tcp 連線數監控圖
附部落格專案所使用的 Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base WORKDIR /app EXPOSE 80 EXPOSE 443 RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list RUN apt-get update && apt-get install -y curl FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build WORKDIR /src COPY src/*.sln src/*.props src/NuGet.config ./ COPY src/*/*.csproj ./ RUN for file in $(ls *.csproj); do mkdir -p ${file%.*}/ && mv $file ${file%.*}/; done RUN dotnet restore "BlogServerCore.sln" COPY src/. . RUN dotnet build "BlogServerCore.sln" -c Release --no-restore FROM build AS publish WORKDIR /src/BlogServer.WebApi RUN dotnet publish "BlogServer.WebApi.csproj" -c Release -o /app/publish --no-build FROM base AS final WORKDIR /app COPY --from=publish /app/publish . RUN echo "dotnet BlogServer.WebApi.dll" > run.sh HEALTHCHECK --interval=5s --timeout=20s \ CMD curl -fs -o /dev/null localhost/alive || exit 1