背景:
嗨,我在Azure上运行MongoDB副本集,并在Android应用程序中远程连接到它。我已经从所有实例中获得了很好的读取功能(更新:因为它们可以在主节点和辅助节点上读取)。但是,对数据库的写入仍然存在间歇性错误,并出现以下错误,因为写操作必须仅在主节点上完成。
此外,如果您可以提供任何更具体的资源来处理此问题,那么这也将非常有用。我已经浏览了大部分文档并对此错误进行了大量搜索。
问题:
如何防止此错误并允许100%的时间写入?
E/AndroidRuntime(): com.mongodb.WriteConcernException: {
"serverUsed" : "/<my-remote-ip>:27017" , "err" : "not master" ,
"code" : 10058 , "n" : 0 , "lastOp" : { "$ts" : 0 , "$inc" : 0} ,
"connectionId" : 1918 , "ok" : 1.0}
堆栈跟踪:
E/AndroidRuntime(13731): FATAL EXCEPTION: Thread-7629
E/AndroidRuntime(13731): Process: com.myapplication.examplemongodb, PID: 13731
E/AndroidRuntime(13731): com.mongodb.WriteConcernException: { "serverUsed" : "/<my-remote-ip>:27017" , "err" : "not master" , "code" : 10058 , "n" : 0 , "lastOp" : { "$ts" : 0 , "$inc" : 0} , "connectionId" : 1918 , "ok" : 1.0}
E/AndroidRuntime(13731): at com.mongodb.CommandResult.getException(CommandResult.java:77)
E/AndroidRuntime(13731): at com.mongodb.CommandResult.throwOnError(CommandResult.java:110)
E/AndroidRuntime(13731): at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:102)
E/AndroidRuntime(13731): at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:142)
E/AndroidRuntime(13731): at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:115)
E/AndroidRuntime(13731): at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:248)
E/AndroidRuntime(13731): at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
E/AndroidRuntime(13731): at com.mongodb.DBCollection.insert(DBCollection.java:76)
E/AndroidRuntime(13731): at com.mongodb.DBCollection.insert(DBCollection.java:60)
E/AndroidRuntime(13731): at com.mongodb.DBCollection.insert(DBCollection.java:105)
E/AndroidRuntime(13731): at com.myapplication.examplemongodb.ActivityMain$1.run(ActivityMain.java:83)
E/AndroidRuntime(13731): at java.lang.Thread.run(Thread.java:841)
备注:
可能的解决方案:
更新:
TCP Input Endpoint
端口27017。正如@David所说,我目前无法控制连接哪个实例。HTTP Input Endpoint
。这只是默认使用我上面提到的mongo-azure库。我不确定我是否应该采取任何措施。答案 0 :(得分:1)
如果实例都位于单个负载平衡Input
端点(例如27017)后面,则每次客户端计算机连接到端点时,它都将连接到复制集群中可能不同的节点(而且你无法控制你去过哪个实例)。这可能解释了为什么有时会尝试写入非master并获取错误,但所有读取都有效(因为您可能设置了MongoDB集群以允许在辅助节点上读取)。
辅助角色还支持InstanceInput
个端点,允许您设置面向外部的端口范围(例如,27017-27019),映射到工作器实例本身的单个端口(例如27017)。如果您这样做,您的客户端应用程序现在可以直接连接到所有三个实例(27017,27018,27019)。许多驱动程序支持replicaset连接,因此它可以确定哪个节点是主节点,将所有写入指向它。 我不知道您在Android上使用的驱动程序是否支持复制副本。如果驱动程序不支持复制副本,那么您可能需要考虑建立一个API层然后执行所有操作与数据库的通信(总的来说,这是一个很好的做法,你可以通过Azure的移动服务快速实现这一点)。
所以......如果你的replicaset集群的端点配置为Input
,这可能解释了你所看到的问题,应该通过将端点类型切换为InstanceInput
来解决这个问题。