今天咱們分析了博客站點的2次故障(故障一、故障二),發現一個巧合的地方,.NET 5.0 正式版的 docker 鏡像是在11月10日提早發佈上線的。html
而在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服務器上生成應用的生產環境鏡像)。web
如今能夠進入這2個發佈版本的鏡像進行驗證docker
$ 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。app
因此這2次故障時用的都是基於 .NET 5.0 正式版的鏡像,並且11月10日至11月12日期間,咱們只進行了2次發佈,2次都出現了故障。curl
若是片面地從這個巧合來看,彷佛故障與 .NET 5.0 正式版鏡像有關,這時你可能立馬提出疑問,一樣是基於 .NET 5.0 正式版的鏡像,爲何今天早上發佈沒有出現故障?tcp
根據咱們的分析判斷,故障的觸發與發佈時的併發請求量有關,2次故障時的發佈時間分別是在 20:30 與 19:30 左右,這2個發佈時間點的併發量差很少,而今天早上發佈時併發量要小不少,並且咱們其餘併發量不大的應用升級到 .NET 5.0 沒有出現過這個問題,因此今天早上發佈正常極可能是由於沒有到達觸發故障的併發量。memcached
另外,今天早上發佈時咱們已經將博客項目依賴的下面這些 nuget 包升級到 .NET 5.0 正式版對應的版本,昨天晚上在處理故障時也進行過這個升級發佈嘗試,但沒有解決問題,與故障關聯的可能性很小,但從中能夠獲得的信息是故障時項目代碼是基於 .NET 5.0 RC 2,生產環境部署的 runtime 是基於 .NET 5.0 正式版。ui
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