Как правильно отключить mongod в методе `RoleEntryPoint.OnStop ()` - PullRequest
2 голосов
/ 11 июня 2011

Мне нужно изящно завершить работу mongod.exe, который запускается методом System.Diagnostics.Process в RoleEntryPoint.OnStop().

Меня вдохновила статья Запуск MongoDb в Microsoft Windows Azure с 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();
}

Как я понял, что родительский процесс удерживает блокировку? Я просто изменил процесс для запуска в новом окне оболочки, где не было перенаправлено вывода (startInfo.UseShellExecute = true). Запустились два окна консоли, и когда mongod был закрыт, он снял блокировку до того, как основное приложение было прекращено . Мне нужно добиться такого поведения, чтобы использовать его в RoleEntryPoint в Windows Azure.

Кто-нибудь знает как?

EDIT:

Я понял, что, возможно, это родительский процесс, у которого есть слушатели ErrorDataReceived и OutputDataReceived, которые поддерживают правильное закрытие / сброс потока вывода mongod в mongod.lock ... это может быть?

Ответы [ 3 ]

2 голосов
/ 11 июня 2011

В методе OnStop вы можете вызвать команду отключения . Вы могли бы сделать что-то вроде

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

Если вы используете официальный драйвер 1.0, команда выключения зависает, даже если она выключила сервер. Azure перезапустит этот экземпляр роли, несмотря на зависание, поскольку вы получаете только около 30 секунд в OnStop. Эта ошибка была исправлена ​​в последней версии драйвера в GitHub https://github.com/mongodb/mongo-csharp-driver.

Дополнительно использовать mongodb 1.8.1 с включенным ведением журнала . Вам не понадобится ремонт тогда. Это необходимо, если по какой-то причине Azure перезагружает экземпляр роли до завершения выключения и не очищается. Более подробную информацию о ведении журнала можно найти по адресу http://www.mongodb.org/display/DOCS/Journaling

1 голос
/ 11 июня 2011

Спасибо за ответ Шридхара, просто чтобы подвести итог и добавить некоторый код для других в качестве ссылки.

Запуск процесса с ведением журнала

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")

0 голосов
/ 11 июня 2011

Разве вы не можете просто сделать _mongoProcess.Kill () в OnStop ()?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...