我们有一个Scala服务器,它使用由Casbah包装的Java MongoDB驱动程序。最近,我们使用Mongo API将其数据库从实际的MongoDB切换到Azure CosmosDB。这通常工作正常,但是偶尔对Cosmos的调用因MongoSocketWriteException(下面的堆栈跟踪)而失败。
我们正在创建客户端
import com.mongodb.casbah.Imports._
val mongoUrl = "mongodb://username:password@host.documents.azure.com:10255/?ssl=true&replicaSet=globaldb"
val client = MongoClient(MongoClientURI(mongoUrl))
val collection: MongoCollection = client("mongoDatabase")("mongoCollection")
我们尝试从连接URI中删除&replicaSet=globaldb
,因为这个看似相似的错误(How to solve MongoError: pool destroyed while connecting to CosmosDB)的建议解决方法,但它没有解决问题。
堆栈追踪:
com.mongodb.MongoSocketWriteException: Exception sending message
at com.mongodb.connection.InternalStreamConnection.translateWriteException(InternalStreamConnection.java:462)
at com.mongodb.connection.InternalStreamConnection.sendMessage(InternalStreamConnection.java:205)
at com.mongodb.connection.UsageTrackingInternalConnection.sendMessage(UsageTrackingInternalConnection.java:95)
at com.mongodb.connection.DefaultConnectionPool$PooledConnection.sendMessage(DefaultConnectionPool.java:424)
at com.mongodb.connection.CommandProtocol.sendMessage(CommandProtocol.java:209)
at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.java:111)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:286)
at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.java:173)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:215)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:206)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:112)
at com.mongodb.operation.CountOperation$1.call(CountOperation.java:210)
at com.mongodb.operation.CountOperation$1.call(CountOperation.java:206)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:230)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:203)
at com.mongodb.operation.CountOperation.execute(CountOperation.java:206)
at com.mongodb.operation.CountOperation.execute(CountOperation.java:53)
at com.mongodb.Mongo.execute(Mongo.java:772)
at com.mongodb.Mongo$2.execute(Mongo.java:759)
at com.mongodb.DBCollection.getCount(DBCollection.java:962)
at com.mongodb.DBCursor.count(DBCursor.java:670)
at com.mongodb.casbah.MongoCollectionBase.getCount(MongoCollection.scala:496)
at com.mongodb.casbah.MongoCollectionBase.getCount$(MongoCollection.scala:488)
at com.mongodb.casbah.MongoCollection.getCount(MongoCollection.scala:1106)
at com.mongodb.casbah.MongoCollectionBase.count(MongoCollection.scala:897)
at com.mongodb.casbah.MongoCollectionBase.count$(MongoCollection.scala:894)
at com.mongodb.casbah.MongoCollection.count(MongoCollection.scala:1106)
[snip]
Caused by: java.net.SocketException: Broken pipe (Write failed)
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
at sun.security.ssl.OutputRecord.writeBuffer(OutputRecord.java:431)
at sun.security.ssl.OutputRecord.write(OutputRecord.java:417)
at sun.security.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:876)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:847)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
at com.mongodb.connection.SocketStream.write(SocketStream.java:75)
at com.mongodb.connection.InternalStreamConnection.sendMessage(InternalStreamConnection.java:201)
... 38 common frames omitted
(发布这个答案是因为我希望这个解决方案对其他人有用,因为我欢迎任何进一步的见解。)
答案 0 :(得分:5)
我们将&maxIdleTimeMS=1500000
添加到连接URI后,问题就消失了,以便将最大连接空闲时间设置为25分钟。
原因似乎是Azure服务器上的空闲连接超时30分钟,而Mongo客户端的默认行为根本没有空闲超时。服务器不会传达它正在将空闲连接丢弃回客户端的事实,因此下次尝试使用它会因上述错误而失败。将最大连接空闲时间设置为小于30分钟的值会使我们的服务器在Azure服务器终止之前关闭空闲连接。在使用连接之前某种保持活动或检查也可能是可能的。
我实际上无法找到有关此问题的任何文档或其他对此问题的引用,尽管它可能由Azure内部负载均衡器的TCP连接的30分钟空闲超时引起或与之相关(请参阅例如https://feedback.azure.com/forums/217313-networking/suggestions/18823588-increase-idle-timeout-on-internal-load-balancers-t)。
答案 1 :(得分:0)
您可以使用设置时间
var options = new MongoClientOptions.Builder()
.socketKeepAlive(true)
.heartbeatFrequency(1000)
.maxConnectionIdleTime(18000)
var clientUri = new MongoClientURI(uri,options)
尝试一次