Asp.net 9 在运行子进程时挂在 docker 容器中

问题描述 投票:0回答:1

我有一个 ASP.NET 9 应用程序在 Linux Docker 容器中运行。

使用此 dockerfile 制作:

FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app

# Install base components
RUN apt update && \
    apt install -y curl htop nano
RUN curl -sSL https://get.docker.com/ | sh

# Set up the build env
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /source

# Install NuGet Packages
COPY "src/Dictus.AsrEvaluator.Backend/Dictus.AsrEvaluator.Backend.csproj" "src/Dictus.AsrEvaluator.Backend/Dictus.AsrEvaluator.Backend.csproj"
COPY "src/SunShared/Dictus.Sun.Shared/Dictus.Sun.Shared.csproj" "src/SunShared/Dictus.Sun.Shared/Dictus.Sun.Shared.csproj"
RUN dotnet restore "src/SunShared/Dictus.Sun.Shared/Dictus.Sun.Shared.csproj"
RUN dotnet restore "src/Dictus.AsrEvaluator.Backend/Dictus.AsrEvaluator.Backend.csproj"

# Build the app
COPY "src/" "src/"
ARG VersionSuffix=0
RUN dotnet publish "src/Dictus.AsrEvaluator.Backend/Dictus.AsrEvaluator.Backend.csproj" -c Release -o /app /p:VersionSuffix=$VersionSuffix

# Copy the app to the final build image
FROM base AS final
WORKDIR /app
COPY --from=build /app .

# Setup defaults
HEALTHCHECK CMD curl --max-time 10 --fail http://localhost:80/health || exit 1
ENV ASPNETCORE_HTTPS_PORTS=80
ENTRYPOINT ["dotnet", "Dictus.AsrEvaluator.Backend.dll"]

但偶尔它会完全挂起。

我检测到挂起

  • 当尝试连接到像 https://my-url.com 这样的服务器时,它永远不会产生响应。我尝试添加一个仅返回常量数字的端点,但该端点永远不会返回。
  • docker 容器正在运行,我可以
    docker exec
    进入 docker 容器并查看 dotnet 进程仍在运行。 dotnet 进程不使用任何 CPU,并且具有正常的大量 RAM 使用量。就像进程只是闲置一样。
  • docker 容器内的 top 给出以下输出:
PID USER    PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
1 root      20   0  263.8g 641220 196992 S   0.0   2.0 242:33.04 dotnet

我尝试从我的申请中获取一些信息。在 docker 容器内,我尝试安装并运行:

  • dotnet-counters monitor --process-id 1
  • dotnet-trace collect -p 1
  • dotnet-dump collect --process-id 1

他们都无法从我的申请中获取任何信息。

dotnet-trace collect
dotnet-counters monitor
都完全挂起,我无法使用CTRL+C退出它们,我必须关闭终端。
dotnet-dump
永远不会创建任何内容或将任何内容写入其输出文件。

应用程序日志在挂起时停止,不提供任何附加信息。

什么时候挂?

偶尔我的应用程序会收到一份新工作。为了处理此作业,它准备了许多文件和文件夹,然后启动 2 个并行运行的子进程来完成作业。 当 2 个子进程运行时,主 ASP.NET 9 应用程序挂起。应用程序是否挂起是非常随机的。我可以运行几周而没有任何问题,然后突然挂起,或者可能只是挂起前几天。

ASP.NET 9 应用程序启动 2 个子进程并监听它们的 STDOUT 和 STDERR

 ProcessStartInfo startInfo = new ProcessStartInfo
 {
     WindowStyle = ProcessWindowStyle.Hidden,
     RedirectStandardOutput = true,
     RedirectStandardError = true,
     UseShellExecute = false,
     FileName = "docker -v /job_data:/job_data run my_other_docker",
     Arguments = arguments,
 };
 using Process process = new Process
 {
     StartInfo = startInfo,
     EnableRaisingEvents = true
 };
  //Outputs
 StringBuilder stdOut = new StringBuilder();
 StringBuilder stdErr = new StringBuilder();
 
  //Runs the command
 process.Start();

 ReadStream(process.StandardOutput, stdOut, progress, true);
 ReadStream(process.StandardError, stdErr, progress, false);
 
  while (!process.HasExited || !isReadStdOutDone || !isReadErrOutDone)
 {
     if (token.IsCancellationRequested)
     {
         process.Kill();

         token.ThrowIfCancellationRequested();
     }

     await Task.Delay(100);
 }

 //Reads the output
 string stdout = stdOut.ToString();
 string stderr = stdErr.ToString();
 
  private void ReadStream(
     StreamReader stream,
     StringBuilder read,
     IProgress<string>? progress,
     bool isStdOut)
 {
     Task.Run(async () =>
     {
         var line = CleanLogLine(await stream.ReadLineAsync());
         while (line != null)
         {
             line = $"{name} - {line}";
             read.AppendLine(line);
             if (progress != null)
                 progress.Report(line);
             line = CleanLogLine(await stream.ReadLineAsync());
         }
         if (isStdOut)
             isReadStdOutDone = true;
         else
             isReadErrOutDone = true;
     });
 }

 private string? CleanLogLine(string? line)
 {
     if (line != null &&
         line.Count(x => x == '\b') > 1000)
     {
         line = line[0..1000];
     }
     return line;
 }
 

我的应用程序在 2 个子进程运行时挂起。我可以看到两个子进程都成功完成。所以我怀疑问题出在子进程上。

想法和想法

  • 据我所知这不是内存泄漏(内存不足异常)。
  • 不知道是不是线程停滞。正如我提到的
    dotnet-counters
    等无法提供任何输出。
  • 我不知道是否是我处理 STDOUT 和 STDERR 的方式导致了问题

如何继续调试并找出挂起的原因?

asp.net docker process
1个回答
0
投票

确保 docker 设置中有足够的线程余量,还要确保在使用后正确关闭线程,因为如果没有正确关闭,线程将停留并导致阻塞,最终由于资源占用而停止在 docker 中

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.