mongoDB 常見三種異常解析 (附配置)
阿新 • • 發佈:2019-01-07
配置
mongoDB配置
<mongo:mongo-client id="mongoClient" host="${mongo.host}" port="${mongo.port}" credentials="${mongo.user}:${mongo.pwd}@${mongo.defaultDbName}">
<mongo:client-options
connections-per-host="${mongo.connectionsPerHost}"
min-connections-per-host= "${mongo.minConnectionsPerHost}"
threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
connect-timeout="${mongo.connectTimeout}"
max-wait-time="${mongo.maxWaitTime}"
socket-keep-alive="${mongo.socketKeepAlive}"
socket-timeout="${mongo.socketTimeout}"
description="${mongo.description}"
max-connection-idle-time="${mongo.maxConnectionIdleTime}"
max-connection-life-time="${mongo.maxConnectionLifeTime}"
heartbeat-socket-timeout="${mongo.heartbeatSocketTimeout}"
heartbeat-connect-timeout="${mongo.heartbeatConnectTimeout}"
min-heartbeat-frequency="${mongo.minHeartbeatFrequency}"
heartbeat-frequency="${mongo.heartbeatFrequency}" />
</mongo:mongo-client>
mongo.host=127.0.0.1
mongo.port=27017
mongo.defaultDbName=data
mongo.user=test
mongo.pwd=123456
# 最大連線數,每一臺伺服器
mongo.connectionsPerHost=1
# 可阻塞執行緒佇列容量
mongo.threadsAllowedToBlockForConnectionMultiplier=5
# 每一臺伺服器的最小連線數
mongo.minConnectionsPerHost=1
#連線超時時間 1分鐘
mongo.connectTimeout=60000
#等待時間 120000 2 * 60 * 1000
mongo.maxWaitTime=120000
#Socket超時時間
mongo.socketTimeout=0
#保持連線
mongo.socketKeepAlive=true
mongo.description=mongodb
## 連線空閒時間8小時,否則連線太過頻繁
mongo.maxConnectionIdleTime=28800000
mongo.maxConnectionLifeTime=0
#mongo 心跳
mongo.heartbeatSocketTimeout=10000
mongo.heartbeatConnectTimeout=15000
mongo.minHeartbeatFrequency=5000
mongo.heartbeatFrequency=100000
異常1 MongoWaitQueueFullException
請求執行緒過多時,阻塞的執行緒放入不到佇列之中,
執行緒數量 - connectionsPerHost > threadsAllowedToBlockForConnectionMultiplier * connectionsPerHost
執行緒數量 = connectionsPerHost * (threadsAllowedToBlockForConnectionMultiplier + 1)
根據以上公式可以得出
增大threadsAllowedToBlockForConnectionMultiplier 或者 connectionsPerHost 即可
通過多執行緒模擬即可
com.mongodb.MongoWaitQueueFullException: Too many threads are already waiting for a connection. Max number of threads (maxWaitQueueSize) of 5 has been exceeded.
at com.mongodb.connection.DefaultConnectionPool.createWaitQueueFullException(DefaultConnectionPool.java:274)
at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:93)
at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:86)
at com.mongodb.connection.DefaultServer.getConnection(DefaultServer.java:77)
at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection(ClusterBinding.java:86)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:422)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:415)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:133)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:60)
at com.mongodb.Mongo.execute(Mongo.java:819)
at com.mongodb.Mongo$2.execute(Mongo.java:802)
at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:340)
at com.mongodb.DBCollection.insert(DBCollection.java:335)
at com.mongodb.DBCollection.insert(DBCollection.java:326)
at com.mongodb.DBCollection.insert(DBCollection.java:296)
at com.mongodb.DBCollection.insert(DBCollection.java:262)
at com.mongodb.DBCollection.insert(DBCollection.java:199)
at org.springframework.data.mongodb.core.MongoTemplate$9.doInCollection(MongoTemplate.java:1054)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:482)
... 22 more
異常2 MongoTimeoutException
阻塞佇列的執行緒等待連線超時
解決方案:: 增大maxWaitTime引數
復現方案: 通過多執行緒、大資料量,無索引查詢。調小maxWaitTime測試即可
Caused by: com.mongodb.MongoTimeoutException: Timeout waiting for a pooled item after 5000 MILLISECONDS
at com.mongodb.internal.connection.ConcurrentPool.get(ConcurrentPool.java:127)
at com.mongodb.connection.DefaultConnectionPool.getPooledConnection(DefaultConnectionPool.java:256)
at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:97)
at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:86)
at com.mongodb.connection.DefaultServer.getConnection(DefaultServer.java:77)
at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection(ClusterBinding.java:86)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:431)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:406)
at com.mongodb.operation.FindOperation.execute(FindOperation.java:709)
at com.mongodb.operation.FindOperation.execute(FindOperation.java:81)
at com.mongodb.Mongo.execute(Mongo.java:810)
at com.mongodb.Mongo$2.execute(Mongo.java:797)
at com.mongodb.DBCursor.initializeCursor(DBCursor.java:871)
at com.mongodb.DBCursor.hasNext(DBCursor.java:142)
at com.mongodb.DBCursor.one(DBCursor.java:680)
at com.mongodb.DBCollection.findOne(DBCollection.java:831)
at com.mongodb.DBCollection.findOne(DBCollection.java:794)
at com.mongodb.DBCollection.findOne(DBCollection.java:741)
at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2197)
at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2181)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1925)
... 18 more
異常3 MongoInterruptedException
由於執行緒被中斷導致mongo查詢被中斷
查詢中斷異常
Caused by: com.mongodb.MongoInterruptedException: Interrupted acquiring a permit to retrieve an item from the pool
at com.mongodb.internal.connection.ConcurrentPool.acquirePermit(ConcurrentPool.java:186)
at com.mongodb.internal.connection.ConcurrentPool.get(ConcurrentPool.java:126)
at com.mongodb.connection.DefaultConnectionPool.getPooledConnection(DefaultConnectionPool.java:256)
at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:97)
at com.mongodb.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:86)
at com.mongodb.connection.DefaultServer.getConnection(DefaultServer.java:77)
at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection(ClusterBinding.java:86)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:422)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:397)
at com.mongodb.operation.CountOperation.execute(CountOperation.java:232)
at com.mongodb.operation.CountOperation.execute(CountOperation.java:55)
at com.mongodb.Mongo.execute(Mongo.java:810)
at com.mongodb.Mongo$2.execute(Mongo.java:797)
at com.mongodb.DBCollection.getCount(DBCollection.java:1004)
at com.mongodb.DBCollection.count(DBCollection.java:854)
at org.springframework.data.mongodb.core.MongoTemplate$8.doInCollection(MongoTemplate.java:779)
at org.springframework.data.mongodb.core.MongoTemplate$8.doInCollection(MongoTemplate.java:777)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:482)
... 33 common frames omitted
Caused by: java.lang.InterruptedException: null
at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1326)
at java.util.concurrent.Semaphore.tryAcquire(Semaphore.java:409)
at com.mongodb.internal.connection.ConcurrentPool.acquirePermit(ConcurrentPool.java:180)
... 50 common frames omitted
復現程式
final Thread t1 = new Thread(() -> {
userRepository.findOneByName(UUID.randomUUID().toString());
userRepository.findOneByName(UUID.randomUUID().toString());
userRepository.findOneByName(UUID.randomUUID().toString());
userRepository.findOneByName(UUID.randomUUID().toString());
userRepository.findOneByName(UUID.randomUUID().toString());
userRepository.findOneByName(UUID.randomUUID().toString());
});
t1.start();
Thread.sleep(10000);
t1.interrupt();
while (true) {
}