如何在`RoleEntryPoint.OnStop()`方法中正常关闭mongod

时间:2011-06-10 23:12:20

标签: c# .net mongodb azure

我需要在System.Diagnostics.Process方法中正常关闭以RoleEntryPoint.OnStop()启动的mongod.exe。

我受到Running MongoDb on Microsoft Windows Azure with CloudDrive文章的启发。 一切似乎都运行良好,但是在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 ...它可以吗?

3 个答案:

答案 0 :(得分:2)

OnStop方法中,您可以invoke the shutdown command。你可以做点什么

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

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

另外use mongodb 1.8.1 with journaling enabled。那时你不需要修理。如果由于某种原因Azure在关闭完成之前回收角色实例并且不干净,则需要这样做。有关日记的更多信息,请访问http://www.mongodb.org/display/DOCS/Journaling

答案 1 :(得分:1)

感谢Sridhar的回答,只是为了重新概括并为其他人添加一些代码作为参考。

使用日记功能启动流程

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

关闭,然后等待5秒钟进行退出。在我最新的官方mongo-csharp驱动程序中,它从EndOfStreamException抛出MongoDB.Driver.dll!MongoDB.Driver.Internal.MongoConnection.ReceiveMessage。我希望很快就能解决。

    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();
        }
    }

编辑:使用server.Shutdown()代替server.RunAdminCommand("shutdown")

答案 2 :(得分:0)

你不能在OnStop()中做_mongoProcess.Kill()吗?