2011-06-10 20 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