7

3つのインスタンスのレプリカセットを使用して、公式のMongoDB C#ドライバーをテストしてきました。ループでレプリカセットにアクセスする簡単なアプリを作成しました。

私の質問は次のとおりです。プライマリサーバーを閉じるときに、現在のようにEndOfStreamExceptionをスローせずに、C#ドライバーでクエリを自動的に再実行することはできますか?

MongoServerSettingsの初期化コードは次のとおりです。

        var settings = new MongoServerSettings()
        {
            ConnectionMode = ConnectionMode.ReplicaSet,
            ReplicaSetName = "mongors",
            ReadPreference = new ReadPreference(ReadPreferenceMode.PrimaryPreferred),
            SafeMode = SafeMode.True,
            DefaultCredentials = new MongoCredentials("user", "password"),
            Servers = new[] { new MongoServerAddress("server.net", 27020), 
                        new MongoServerAddress("server.net", 27019),
                        new MongoServerAddress("server.net", 27018)}

        };

そして、これが私がサーバーに問い合わせるコードです:

        while (true)
        {
            var server = MongoServer.Create(settings);
            var db = server.GetDatabase("db");
            var collection = db.GetCollection<TaggedAction>("actions");
            var query = Query.EQ("_id", id);
            var entity = collection.FindOne(query);

            Console.WriteLine(DateTime.Now +" " + entity.ActionName);

            Thread.Sleep(2500);
        }

プライマリサーバーをシャットダウンすると、クライアントは次の例外をスローします。

System.IO.EndOfStreamException was unhandled
  HResult=-2147024858
  Message=Attempted to read past the end of the stream.
  Source=MongoDB.Bson
  StackTrace:
       at MongoDB.Bson.IO.BsonBuffer.LoadFrom(Stream stream, Int32 count) in C:\work\rstam\mongo-csharp-driver\Bson\IO\BsonBuffer.cs: line 314
       at MongoDB.Bson.IO.BsonBuffer.LoadFrom(Stream stream) in C:\work\rstam\mongo-csharp-driver\Bson\IO\BsonBuffer.cs: line 281
       at MongoDB.Driver.Internal.MongoConnection.ReceiveMessage(BsonBinaryReaderSettings readerSettings, IBsonSerializationOptions serializationOptions) in C:\work\rstam\mongo-csharp-driver\Driver\Internal\MongoConnection.cs: line 478
       at MongoDB.Driver.MongoCursorEnumerator`1.GetReply(MongoConnection connection, MongoRequestMessage message) in C:\work\rstam\mongo-csharp-driver\Driver\Core\MongoCursorEnumerator.cs: line 296
       at MongoDB.Driver.MongoCursorEnumerator`1.GetFirst() in C:\work\rstam\mongo-csharp-driver\Driver\Core\MongoCursorEnumerator.cs: line 253
       at MongoDB.Driver.MongoCursorEnumerator`1.MoveNext() in C:\work\rstam\mongo-csharp-driver\Driver\Core\MongoCursorEnumerator.cs: line 141
       at System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source)
       at MongoDB.Driver.MongoCollection.FindOneAs(IMongoQuery query) in C:\work\rstam\mongo-csharp-driver\Driver\Core\MongoCollection.cs: line 557
       at MongoDB.Driver.MongoCollection`1.FindOne(IMongoQuery query) in C:\work\rstam\mongo-csharp-driver\Driver\Core\MongoCollection.cs: line 1734
       at ConsoleApplication16.Program.Main(String[] args) in Program.cs: line 53
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:           

この例外を飲み込んでループを続行すると、すべてが機能します。そのため、問題を解決して別のサーバーに切り替えることができます。しかし、ドライバーがこれを自動的に処理して、例外をスローしないようにできれば素晴らしいと思います。出来ますか?

4

1 に答える 1

7

多くの場合、実行中のカーソルはプライマリサーバーにのみ存在するため、フェイルオーバーは不可能です。セカンダリーはそれについて何も知らないので、それを続けることができませんでした。

あなたの場合、あなたはあなたが継続したいと思っていることを知っていますが、あなたのニーズを受け入れてすべての状況に適用することは私たちの思いがけないことです。ループを続行したい場合、他の人はそうではないかもしれません。

それ以外の場合、一部のドライバーはクエリを再試行します。.NETドライバーは、正しい動作を常に確認できるとは限らないため、アプリケーションに任せて決定するためではありません。

PrimaryPreferredの場合、読み取りをプライマリから取得する必要がある理由があります。これは、それらが最新であるためです。サイレントにセカンダリにフォールバックすると、セカンダリがどれだけ戻っているかに応じて、クエリがプライマリへの最後の成功したクエリの前の結果を実際に返す可能性があります。これは良い経験ではないため、私たちは単にそれを行わず、これらのエラーをキャッチして再試行を自分で処理することをお勧めします。

これらのエラーの一部をMongoDB固有の例外でラップすることを検討しているため、EndOfStream例外(https://jira.mongodb.org/browse/CSHARP-474)などを推測する必要はありません。さらに、この機能を確認したい場合は、jiraを提出してください。これを予測可能な方法で実行する方法を検討します。おそらく、再試行を処理するためのユーザー提供の戦略(IRetryStrategyなど)を使用します。

于 2012-10-06T18:26:08.513 に答える