如何在`RoleEntryPoint中优雅地关闭mongod.OnStop()`方法

本文关键字:mongod OnStop 方法 RoleEntryPoint | 更新日期: 2023-09-27 17:58:49

我需要优雅地关闭用RoleEntryPoint.OnStop()方法中的System.Diagnostics.Process启动的mongod.exe。

我受到一篇文章的启发,该文章使用CloudDrive在Microsoft Windows Azure上运行MongoDb。一切似乎都很好,但在WorkerRole重启后,mongod表示:

**************
old lock file: .'mongod.lock.  probably means unclean shutdown
recommend removing file and running --repair
see: http://dochub.mongodb.org/core/repair for more information
*************

所以我创建了一个简单的控制台应用程序,下面的代码模拟了mongod.exe被杀死时的相同结果。只有当控制台窗口(父进程)关闭时,才会释放锁定文件。由于CloudDrive在父进程终止之前被卸载RoleEntryPoint),mongod.lock文件从未在Windows Azure WorkerRole环境中发布。

static void Main(string[] args)
{
    StartMongo();
    Console.ReadLine();
    _mongoProcess.Close();
}
private static void StartMongo()
{
    _mongoProcess = new Process();
    var startInfo = _mongoProcess.StartInfo;
    startInfo.UseShellExecute = false;
    startInfo.CreateNoWindow = false;
    startInfo.FileName = @"mongod.exe";
    startInfo.WorkingDirectory = Environment.CurrentDirectory;
    startInfo.Arguments = "--dbpath .";
    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;
    _mongoProcess.ErrorDataReceived += (sender, evt) => WriteLine(evt.Data);
    _mongoProcess.OutputDataReceived += (sender, evt) => WriteLine(evt.Data);
    _mongoProcess.Start();
    _mongoProcess.BeginErrorReadLine();
    _mongoProcess.BeginOutputReadLine();
}

我是如何意识到父进程在保持锁定的?我只是简单地将进程更改为在新的shell窗口中运行,并没有重定向任何输出(startInfo.UseShellExecute = true)。启动了两个控制台窗口,当mongod关闭时,它在主应用程序终止前释放了锁定。我需要实现此行为才能在Windows Azure中的RoleEntryPoint中使用它。

有人知道怎么做吗?

编辑:

我意识到,也许是父进程拥有ErrorDataReceivedOutputDataReceived的侦听器,它们将mongod输出流正确地关闭/刷新到mongod.lock……会吗?

如何在`RoleEntryPoint中优雅地关闭mongod.OnStop()`方法

OnStop方法中,您可以调用关闭命令。你可以做一些类似的事情

  var server = MongoServer.Create("mongodb://host:port");
  server.Shutdown();

如果您使用的是官方的1.0驱动程序,那么即使关闭了服务器,shutdown命令也会挂起。Azure将回收此角色实例,尽管挂起,因为您在OnStop中只有大约30秒的时间。此错误已在GitHub的最新版本驱动程序中修复https://github.com/mongodb/mongo-csharp-driver.

此外,使用mongodb 1.8.1并启用日志。那你就不需要修理了。如果由于某种原因Azure在关闭完成之前回收了角色实例并且没有清理,则需要这样做。有关日记的更多信息,请访问http://www.mongodb.org/display/DOCS/Journaling

感谢Sridhar的回答,只是为了重述并添加一些代码作为参考。

使用日志启动流程

startInfo.Arguments = @"--journal --dbpath c:'path'to'db";

正在关闭,然后等待5秒进行处理以退出。在我最新版本的官方mongo-csharp驱动程序中,它从MongoDB.Driver.dll!MongoDB.Driver.Internal.MongoConnection.ReceiveMessage抛出EndOfStreamException。我希望这个问题能尽快解决。

    var t = new Task(() =>
    {
        var server = MongoServer.Create();
        //server.RunAdminCommand("shutdown"); -- throws exception
        server.Shutdown();
    });
    t.Start();
    try
    {
        t.Wait(5000);
    }
    catch (EndOfStreamException e)
    {
        // silently ignore
    }
    finally
    {
        if (!_mongoProcess.HasExited)
        {
            _mongoProcess.Kill();
        }
    }

EDIT:使用server.Shutdown()而不是server.RunAdminCommand("shutdown")

难道不能只做_mongoProcess吗。OnStop()中的Kill()?