【问题标题】:How to do gracefully shutdown on dotnet with docker?如何使用 docker 在 dotnet 上优雅地关闭?
【发布时间】:2017-04-06 03:33:07
【问题描述】:

有没有办法优雅地 关闭 DOCKER 中运行的 DOTNET CORE 应用程序?如果是,我应该听哪个事件?

我想要的只是在取消请求时,我想将我的取消令牌传递给当前方法,并在它们工作时推迟关闭。

寻找与 dotnet core 相关而非通用信息的示例代码、参考链接等

更新 这个问题不是docker container exits immediately even with Console.ReadLine() in a .net core console application 的重复问题,因为我没有立即退出问题。我需要利用 Windows.SystemsEvents.SessionEnding 之类的事件并依赖 Console.CancelKeyPress 和/或实施 WebHostBuilder() 不符合要求。

【问题讨论】:

  • @cilerler 你的问题被标记为 [asp.net-core]
  • @cilerler 是的,您的问题与 ASP.Net Core 无关,因此它不应包含该标签。添加它只是为了让您的问题有更广泛的受众群体是不正确的做法。
  • 请确保你们有更多关于重复的证据,然后在标记之前再考虑一下。仅仅因为有人认为它是重复的,不应该让你将它标记为重复。它使问题的吸引力降低,并且在做出决定之前应该考虑这样的效果。 强大的力量应该伴随着巨大的责任无论如何,感谢您的关注!

标签: c# .net docker .net-core


【解决方案1】:

System.Console 有一个名为 CancelKeyPress 的事件。我相信这是在将 sigint 事件传递到 dotnet 时触发的。

System.Console.CancelKeyPress += (s,e) => { /* do something here */};

【讨论】:

    【解决方案2】:

    使用 2.0.0-preview2-006497 我做了一些测试,现在当 Docker 向容器发送 SIGTERM/SIGINT 时会触发 AssemblyLoadContext.Default.Unloading .

    示例代码如下:

    System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += ctx =>
    {
        // code here...
    };
    

    有关详细信息,另请参阅此问题:https://github.com/aspnet/Hosting/issues/870

    【讨论】:

      【解决方案3】:

      在 .NET Core 2.0 中,您可以使用 AppDomain.CurrentDomain.ProcessExit 事件,该事件在 Docker 中的 Linux 上运行良好。 AssemblyLoadContext.Default.Unloading 可能也能正常工作,甚至在 .NET Core 2.0 之前。

      【讨论】:

      • 'docker stop ' 将触发 AppDomain.CurrentDomain.ProcessExit。需要注意的是,您的代码只有 2 秒的时间来处理它。请参阅:docs.microsoft.com/en-us/dotnet/api/…github.com/dotnet/coreclr/issues/2688#issuecomment-394843595
      • @J.AndrewLaughlin:是的,时间因环境而异。例如,在 Kubernetes 中,kubectl delete deployment ... 命令似乎触发了 SIGTERM,通常允许应用程序大约 30 秒进行清理。另一方面,kubectl apply ...over 现有部署似乎会立即导致 SIGKILL,根本没有时间进行清理。不幸的是,关于这些行为的文档很少甚至不存在。
      • @cilerler:您对“我需要利用诸如...之类的事件”的担忧似乎已经得到解答。如果是这样,请标记您选择的答案,以便其他人可以更快地找到它。谢谢。
      【解决方案4】:

      如果您的容器在 Linux 中运行,那么 Loader.AssemblyLoadContext.Default.Unloading 可以工作,因为它可以捕获 SIGTERM 信号,但是 Windows 没有对此等效的机制 (dotnet issue)。这是使用 SetConsoleCtrlHandler 在 Windows 中处理关机通知的答案,最初来自 gist

      namespace Routeguide
      {
          using System;
          using System.Threading;
          ...
      
          class Program
          {
              [DllImport("Kernel32")]
              internal static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool Add);
      
              internal delegate bool HandlerRoutine(CtrlTypes ctrlType);
      
              internal enum CtrlTypes
              {
                  CTRL_C_EVENT = 0,
                  CTRL_BREAK_EVENT,
                  CTRL_CLOSE_EVENT,
                  CTRL_LOGOFF_EVENT = 5,
                  CTRL_SHUTDOWN_EVENT
              }
      
              static void Main(string[] args)
              {
                  // do the server starting code
                  Start();
                  ....
      
                  var shutdown = new ManualResetEvent(false);
                  var complete = new ManualResetEventSlim();
                  var hr = new HandlerRoutine(type =>
                  {
                      Log.Logger.Information($"ConsoleCtrlHandler got signal: {type}");
      
                      shutdown.Set();
                      complete.Wait();
      
                      return false;
                  });
                  SetConsoleCtrlHandler(hr, true);
      
                  Console.WriteLine("Waiting on handler to trigger...");
      
                  shutdown.WaitOne();
      
                  Console.WriteLine("Stopping server...");
      
                  // do the server stopping code
                  Stop();
      
                  complete.Set();
                  GC.KeepAlive(hr);
              }
          }
      }
      

      【讨论】:

      • 不适用于 .NET Framework 4.5.2 和 .NET Core 2.0 控制台应用。 Docker 版本 18.05.0-ce-win67 (18263)
      • 对于dotnet core,你可以使用Microsoft.Extensions.Hosting,查看我的这个答案:stackoverflow.com/questions/35176091/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-01
      • 2014-11-03
      • 1970-01-01
      • 1970-01-01
      • 2022-10-15
      • 1970-01-01
      • 2019-01-11
      相关资源
      最近更新 更多