2011-06-10 18 views
2

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

我受到文章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 ......地方呢?

回答

2

OnStop方法你可以invoke the shutdown command。如果您使用的是官方1.0驱动程序shutdown命令挂起,即使它已关闭了服务器,你可以做类似

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

。由于您在OnStop中只有大约30秒的时间,Azure将尽可能回收此角色实例。该错误已在GitHub https://github.com/mongodb/mongo-csharp-driver的驱动程序的最新版本中修复。

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

+0

看来,这将是我的问题的解决方案,但它不是一个答案。我读了日志选项将成为未来版本的默认选项,所以我认为我不需要担心这个,是吗?我希望4倍写入单个插入不会杀死我的CloudDrive。 – 2011-06-11 01:30:15

+1

即使认为日记功能现在不是默认设置,您仍然可以使用它。将--journal与--dbpath一起添加到您的进程参数中。希望有所帮助。 – Sridhar 2011-06-11 02:29:56

+0

感谢您添加关机命令,确切地说应该是什么(除了驱动程序挂起的问题,我将使用来自Github的固定问题)。我将启用日记功能以确保并尝试监控性能。 – 2011-06-11 10:38:34

0

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

+0

不是,它不会写入锁定文件。我需要正确关闭它才能释放锁,并且正如我发现的那样,侦听输出的父进程也需要关闭。 – 2011-06-11 01:12:26

1

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

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

+1

当服务器收到关机命令时,它会在没有回复的情况下关闭套接字。这就是客户端看到EndOfStreamException的原因。我建议你使用server.Shutdown()方法而不是server.RunAdminCommand(“shutdown”),因为它捕获并忽略了EndOfStreamException。 – 2011-06-11 16:33:11

+0

@Robert Stam真棒!我将编辑代码,谢谢。 – 2011-06-11 17:59:56