一 環境介紹
- SpringBoot1.5.13.RELEASE(本地)
- Spring Data MongoDB
- Java 8
- MongoDB(青雲)
二 問題描述
- 使用Studio3T或者Compass等MongoDB的GUI工具連接MongoDB不操作一段時間,就會掉線。但重連速度很快。
- 使用Java的Mongo連接驅動,也是一段時間不操作,再去操作會出現異常(SocketTimeout,能發不能收;連接沒有斷),同樣也是重連速度很快。
# java日志太長,省略一部分
14:03:47.629 [http-nio-8081-exec-5] ERROR c.d.o.c.TestController - Timeout while receiving message; nested exception is com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message
org.springframework.data.mongodb.UncategorizedMongoDbException: Timeout while receiving message; nested exception is com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message
......
Caused by: com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving
message
......
Caused by: java.net.SocketTimeoutException: Read timed out
三 搜索原因
連接被對方丟棄
- MongoDB始終是部署操作系統上,而對於大型公司提供MongoDB的服務會經過層層防火牆、代理服務和負載均衡器。它們把Java保持的連接踢掉了(狀態變成
CLOSE_WAIT
,只能發數據但無法再收到)。 - 於是提了工單問青雲情況,他們反饋就是如果從外網連接需要通過VPN才不會掉線,經過測試將應用部署在青雲服務器上的確沒有問題。
- 如果是自己的服務器搭建mongdb可以參考:https://stackoverflow.com/questions/35597930/sockettimeout-with-opened-connection-in-mongodb 該鏈接解決。(設置:sudo sysctl -w net.ipv4.tcp_keepalive_time=
)
參考:https://segmentfault.com/q/1010000009595664/a-1020000009596082
- 同樣的情況也出現在了微軟的Azure Load Balancer。
四 解決方案
(1)Studio 3T的掉線問題
- 設置 Max connection idle time(連接池中某個連接的空閑時間超過該值,將丟棄該連接並重新新建立一個連接)
參考:https://studio3t.com/knowledge-base/articles/prevent-mongodb-connection-timeout/
(2)SpringBoot中如何設置?
- 方案1:
@Configuration
public class MongoDbSettings {
@Bean
public MongoClientOptions mongoOptions() {
return MongoClientOptions
.builder()
.maxConnectionIdleTime(60000)
.build();
}
}
- 方案2:程序員DD的spring-boot-starter-mongodb-plus
參考:http://blog.didispace.com/springbootmongodb-plus/
(3)應用放到防火牆里面
五 Spring Data Mongo與mongodb-driver的關系
- SpringBoot啟動日志中的一句(由SimpleServerCluster打印的)
14:36:55.672 [restartedMain] INFO org.mongodb.driver.cluster - Cluster created with settings {hosts=[mongodb的IP地址:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
# 這句日志只能顯示簡短的啟動信息,不能作為你修改了配置后是否生效的判斷依據。
- mongodb-driver相關的類
- MongoClientOptions:MongoDB連接的配置類
- MongoClient(繼承Mongo):帶有連接池的Mongo客戶端
- Mongo:帶有連接池的數據庫連接
- DefaultClusterFactory:集群實現的默認工廠
- SimpleServerCluster:真正創建的集群Server連接
- DB:MongoDB集群中邏輯數據庫的線程安全客戶端視圖,用於實際操作MongoDB的類。
- Spring Data Mongo相關的類
- MongoOperations:指定一組基本MongoDB操作的接口。(Spring Data Mongo)
- MongoTemplate(實現MongoOperations):MongoOperations的首要實現類(Spring Data Mongo)
- SimpleMongoDbFactory:一個從Mongo實例創建DB實例的工廠類。(Spring Data Mongo)
注意:篇幅有限,加上比較復雜,以后再詳細研究一下。