2017-09-27 168 views
1

我使用C#驱动程序的2.4.3版连接到MongoDB 3.4.4版。我有一个3成员副本集(一个主要,一个次要,一个仲裁者)。我在连接字符串中设置了关注多数的问题。当主节点和辅助节点都在线时,我可以写入数据库而没有任何问题。但是,当我将主要离线时,我遇到了麻烦。我使用此代码:MongoDB - 写关注大多数 - 尝试读过流末尾

string connectionString = "mongodb://USERNAME:[email protected],SECONDARY/?replicaSet=MyReplicaSet&w=majority"; 

    var client = new MongoClient(connectionString); 
    IMongoDatabase database = client.GetDatabase("test"); 
    IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("people"); 

    Console.WriteLine($"Number of documents: {collection.Count(FilterDefinition<BsonDocument>.Empty)}"); 

    collection.InsertOne(new BsonDocument("name", DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss"))); 

    Console.WriteLine($"Number of documents: {collection.Count(FilterDefinition<BsonDocument>.Empty)}"); 

当我采取的主要下线,第二人当选,我仍然可以写入数据库(我可以看到该文件在数据库上新当选的主)。但调用collection.InsertOne结束投掷MongoDBConnectionException:

MongoDB.Driver.MongoConnectionException: An exception occurred while receiving a message from the server. ---> System.IO.EndOfStreamException: Attempted to read past the end of the stream. 
    at MongoDB.Driver.Core.Misc.StreamExtensionMethods.ReadBytes(Stream stream, Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Connections.BinaryConnection.ReceiveBuffer() 
    --- End of inner exception stack trace --- 
    at MongoDB.Driver.Core.Connections.BinaryConnection.ReceiveBuffer() 
    at MongoDB.Driver.Core.Connections.BinaryConnection.ReceiveBuffer(Int32 responseTo, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Connections.BinaryConnection.ReceiveMessage(Int32 responseTo, IMessageEncoderSelector encoderSelector, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.ConnectionPools.ExclusiveConnectionPool.AcquiredConnection.ReceiveMessage(Int32 responseTo, IMessageEncoderSelector encoderSelector, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.Execute(IConnection connection, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocol[TResult](IWireProtocol`1 protocol, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Servers.Server.ServerChannel.Command[TResult](DatabaseNamespace databaseNamespace, BsonDocument command, IElementNameValidator commandValidator, Func`1 responseHandling, Boolean slaveOk, IBsonSerializer`1 resultSerializer, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase.ExecuteProtocol(IChannelHandle channel, BsonDocument command, Func`1 responseHandling, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase.ExecuteBatch(IChannelHandle channel, BatchableSource`1 requestSource, Int32 originalIndex, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase.ExecuteBatches(IChannelHandle channel, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase.Execute(IChannelHandle channel, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.ExecuteBatch(IChannelHandle channel, Run run, Boolean isLast, CancellationToken cancellationToken) 
    at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.Execute(IWriteBinding binding, CancellationToken cancellationToken) 
    at MongoDB.Driver.OperationExecutor.ExecuteWriteOperation[TResult](IWriteBinding binding, IWriteOperation`1 operation, CancellationToken cancellationToken) 
    at MongoDB.Driver.MongoCollectionImpl`1.ExecuteWriteOperation[TResult](IWriteOperation`1 operation, CancellationToken cancellationToken) 
    at MongoDB.Driver.MongoCollectionImpl`1.BulkWrite(IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken) 
    at MongoDB.Driver.MongoCollectionBase`1.InsertOne(TDocument document, InsertOneOptions options, CancellationToken cancellationToken) 
    at ReplicaSetTest.Program.Main(String[] args) in C:\Code\TFS\Published Register\Main\ReplicaSetTest\Program.cs:line 57 

如果我不写设置关心广大话我也没问题。我对MongoDB的经验并不多,所以我很难理解发生了什么问题。任何人都可以建议我应该从哪里开始追踪这个问题的原因?

感谢,

大卫

回答

1

但调用collection.InsertOne结束了扔MongoDBConnectionException

首先,写担忧多数意味着客户从大多数请求确认的副本集(必须包含主节点)。因此,客户端应用程序将等待来自主节点和其中一个辅助节点的响应。请参阅Verify Write Operations to Replica Sets了解此图。

如果在等待确认写入期间主节点被降级,与主节点的客户端连接将丢失。辅助节点也会尝试清除任何已建立的连接,因为节点的状态已从SECONDARY更改为PRIMARY(另请参阅Replica Set Member States)。这将导致客户端的连接(流)丢失,因为客户端正在等待回复,但它永远不会到来。因此,您得到:

System.IO.EndOfStreamException: Attempted to read past the end of the stream 

您应该尝试捕获此异常,并根据写入的性质进行适当处理。

您可能还有兴趣知道,在MongoDB v3.6中,有Retryable Writes提供处理瞬态网络错误/副本集选举。

此外,我还注意到您的部署由Primary with a Secondary and an Arbiter 而不是Primary with Two Secondaries组成。如果只有2个数据承载节点,并且其中一个数据节点处于关闭状态,则写入关注多数将无法满足要求。由于它要求复制集的大多数接收到写操作,但只有一个数据承载成员处于活动状态。请考虑将仲裁人转换为次要成员。

+0

非常感谢,这是一个很好的详细答案。 – dlarkin77