java - MongoDB+Azure+Android : com. mongodb.WriteConcernException 错误: "not master"代码: "10058"

标签 java android mongodb azure mongodb-java

背景:

您好,我正在 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)

注释:

  • 我正在使用mongo-java-driver v2.11.3 .
  • 我使用了mongo-azure library帮助创建具有两个辅助角色的 MongoDB 副本集。
    • (如果您有更多这方面的资源,那么我很乐意阅读它。我已经阅读了 GitHub 自述文件、 thisthis 以及其他一些与 MongoDB/Azure 无关的内容.但是,这些资源没有更新,也没有详细说明。)

可能的解决方案:

  • 我认为这与拥有副本集有关。
  • 我不确定是否会发生这种情况,因为我只有两个实例副本集(一个主要副本集和一个辅助副本集),并且他们正在为谁想成为主要副本而争论(阅读:投票)。也许,需要仲裁者?但是,我目前不知道该怎么做。

更新:

  • 感谢 @David Makogon 的帮助,我非常确定问题在于我如何设置与 Azure 的连接以及如何访问辅助角色。因此,这是我关于如何配置系统的更新说明:
    • 两个辅助角色 (MongoDB.WindowsAzure.MongoDBRole),我通过 Android 应用中的 TCP 输入端点 端口 27017 直接连接到该角色。正如 @David 所说,我目前无法控制连接到哪个实例。
    • 一个 Web 角色 (MongoDB.WindowsAzure.Manager),我没有对其执行任何操作,但在端口 80 上有一个 HTTP 输入端点。这只是默认使用 mongo-azure 创建的我上面提到的图书馆。我不确定我是否应该对此做些什么。

最佳答案

如果实例全部位于单个负载均衡 Input 后面端点(例如 27017),那么每次您的客户端计算机连接到该端点时,它将连接到复制集集群中可能不同的节点(并且您无法控制您转到哪个实例)。这可能可以解释为什么您有时尝试写入非主节点并收到错误,但所有读取都有效(因为您可能将 MongoDB 集群设置为允许在辅助节点上读取)。

辅助角色还支持InstanceInput端点,它允许您设置面向外部的端口范围(例如 27017-27019),映射到工作实例本身的单个端口(例如 27017)。如果您这样做,您的客户端应用程序现在可以直接连接到所有三个实例(27017、27018、27019)。许多驱动程序支持复制集连接,因此它能够确定哪个节点是主节点,从而将所有写入定向到该节点。 我不知道您在 Android 上使用的驱动程序是否支持复制集。如果驱动程序不支持复制集,那么您可能需要考虑建立一个 API 层,然后它可以完成所有操作与数据库的通信(无论如何,一般来说这是一个值得遵循的良好实践,您可以查看 Azure 的移动服务以获取实现此目的的快速方法)。

所以...如果您的副本集集群的端点配置为 Input ,这可能解释了您所看到的问题,该问题应该可以通过将端点类型切换为 InstanceInput 来解决。 .

关于java - MongoDB+Azure+Android : com. mongodb.WriteConcernException 错误: "not master"代码: "10058",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20449712/

相关文章:

java - 如何从 Firebase 存储获取 URL getDownloadURL

python - 在 Windows 上安装 mongo-connector

python - 如何在 PyMongo 的 GridFS 中打开文件的 GridOut 实例?

java - 确定 CSV 文件中的分类数据与数值数据 --

java - Google 搜索 API 查询选项和排序选项限制

java - 为什么我的两个不同的 angularjs 服务解析为同一个 Restful Java EE Web 服务?

c# - 用于 Java/C# 的 EDIEL 库

android - 在android中将String转换为Double

Perl & MongoDB 二进制数据

android - 从 Activity 获取 Fragment 的抽屉导航