开发者

Howto gracefully shutdown mongod in `RoleEntryPoint.OnStop()` method

开发者 https://www.devze.com 2023-03-12 07:45 出处:网络
I need to gracefully shutdown mongod.exe that is started with System.Diagnostics.Process in RoleEntryPoint.OnStop() method.

I need to gracefully shutdown mongod.exe that is started with System.Diagnostics.Process in RoleEntryPoint.OnStop() method.

I was inspired by an article Running MongoDb on Microsoft Windows Azure with CloudDrive. All seems to work fine, however after WorkerRole restart mongod says:

**************
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
*************

So I created simple Console Application, code below and simulated same result, when mongod.exe is killed. Lock file is released only when console window (parent process) is closed. Because of CloudDrive is unmounted earlier than parent process is terminated (RoleEntryPoint), mongod.lock file is never released in Windows Azure WorkerRole environment.

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

How I realized that parent process is keeping the lock? I simply changed process to run in new shell window, where no output was redirected (startInfo.UseShellExecute = true). Two console windows started and when mongod was closed, it released lock before main application was terminated. I need to achieve this behavior to use it in RoleEntryPoint in Windows Azure.

Does anyo开发者_如何学编程ne know how?

EDIT:

I realized, that maybe it's the parent process, that has the listeners to ErrorDataReceived and OutputDataReceived that holds proper closing/flushing of mongod output stream to mongod.lock ... can it be?


In the OnStop method you can invoke the shutdown command. You could do something like

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

If you are using the official 1.0 driver the shutdown command hangs even though it has shutdown the server. Azure will recycle this role instance in spite of the hang since you get only around 30 seconds in OnStop. This bug has been fixed in the latest version of the driver in GitHub https://github.com/mongodb/mongo-csharp-driver.

Additionally use mongodb 1.8.1 with journaling enabled. You would not need the repair then. This is needed if for some reason Azure recycles the role instance before the shutdown is completed and is not clean. More information on journaling can be found at http://www.mongodb.org/display/DOCS/Journaling


Thanks for Sridhar's answer, just to recapitulate and add some code for others as a reference.

Starting the process with journaling

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

Shutting down and then waiting 5 sec to process to exit. In my latest rev of the official mongo-csharp-driver it throws EndOfStreamException from MongoDB.Driver.dll!MongoDB.Driver.Internal.MongoConnection.ReceiveMessage. I hope this will be fixed soon.

    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: use server.Shutdown() instead of server.RunAdminCommand("shutdown")


Can't you just do _mongoProcess.Kill() in OnStop()?

0

精彩评论

暂无评论...
验证码 换一张
取 消