通过控制台或客户端操作优雅地停止.NET Core服务器



我正在将一些服务器应用程序从.NET Framework+WCF移植到.NET Core,但我在管理服务器出口时遇到了问题。在我们当前的WCF服务器上,我们允许从WCF请求和控制台输入退出:

static void Main()
{
hExit = new ManualResetEvent(false);
StartServer();
Console.WriteLine("Server started. Press [Enter] to quit.");
char key;
while((key=WaitForKeyOrEvent(hExit)) != '' && key != 'r') { }
Console.WriteLine();
StopServer();
}
private static char WaitForKeyOrEvent(System.Threading.WaitHandle hEvent)
{
const int Timeout = 500;
bool dueToEvent = false;
while(!Console.KeyAvailable)
{
if(hEvent.WaitOne(Timeout, false))
{
dueToEvent = true;
break;
}
}
char ret = '';
if(!dueToEvent)
{
ret = Console.ReadKey().KeyChar;
if(ret == '')
ret = char.MaxValue;
}
return ret;
}
...
class ServerObj : IMyWcfInterface
{
void IMyWcfInterface.ExitServer() { hExit.Set(); }
}

这种方法在.NET Core中也适用吗?(当然使用了WCF以外的其他技术,因为它被放弃了(我隐约记得听说KeyAvailable/ReadKey可能不适用于Docker Container中的应用程序,而Containers的使用是";最终目标;正在迁移到.NET Core。。。

通常,在容器中运行时,通常无法访问输入设备(比如键盘(。因此,该选项在容器化应用程序中是不可靠的。

监听某种网络请求(例如,HTTP、grpc、protobuf(可能会起作用,但您必须确保请求的来源是有效的,并且不是攻击您的应用程序并迫使其关闭的恶意实体。

容器环境(例如Kubernetes、Docker(中的惯用方法是,容器引擎向应用程序发送Linux信号,如SIGTERMdocker stop会这样做,Kubernetes在停止pod时也会这样做。然后,您的应用程序应该处理该问题并正确关闭。

根据是否使用ASP.NET Core,实现会有所不同。

在ASP.NET Core中,您可以使用IApplicationLifetime.ApplicationStopping注册一些要在应用程序停止时调用的代码。

这里有一个StackOverflow的答案,它涵盖了实现方面:优雅地关闭asp.net核心

如果未使用ASP.NET Core,则可以处理AppDomain.ProcessExit以注册应用程序停止时要调用的处理程序。

在我的案例中,我有一个启动多个子ASP.NET进程的ASP.NET应用程序。当我关闭IIS时,我希望插件进程正常关闭,所以我添加了一个调用IHostApplicationLifetime.StopApplication()/shutdown GET路由。然而,每当我调用它时,它都会阻塞而不是关闭应用程序。

解决方法是,在我的主机应用程序中,在启动进程的地方,我需要设置UseShellExecute = true。这完全解决了我的问题,因为我的主机应用程序可以对所有插件进程发出GET请求,它们几乎会立即关闭。

奇怪,但事实就是这样。

最新更新