背景 :
嗨,我正在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
HTTP Input Endpoint
如果所有实例都位于单个负载均衡Input端点(例如27017)后面,那么每次您的客户端计算机连接到该端点时,它将连接到副本集群集中可能不同的节点上(并且您无法控制您去过哪个实例)。这可能可以解释为什么您有时会尝试向非主节点写入并得到错误,但所有读取仍然有效(因为您可能将MongoDB集群设置为允许在辅助节点上进行读取)。
Input
辅助角色还支持InstanceInput端点,这些端点使您可以设置一个面向外部的端口范围(例如27017-27019),映射到辅助实例自身上的单个端口(例如27017)。如果执行此操作,您的客户端应用程序现在可以直接连接到所有三个实例(27017、27018、27019)。许多驱动程序支持副本集连接,因此它将能够确定哪个节点是主节点,并将所有写入均定向到该节点。 我不知道您在Android上使用的驱动程序是否支持副本集。 如果驱动程序不支持副本集,则您可能需要考虑建立一个API层,该层随后将所有通信传递给数据库(无论如何,通常遵循的一种良好做法是,您可以查看Azure的移动服务一种快速的实现方法)。
InstanceInput
因此…如果将副本集群集的端点配置为Input,则可能解释了您所看到的问题,可以通过将端点类型切换为来解决该问题InstanceInput。