摘要:本文旨在梳理這些問題,進行一個全面的分析。等到進行數據庫操作的時候,再去中獲取一個連接,進行操作總結通過以上分析,對于以下的數據庫連接池與關系型數據庫連接池并無區別。
摘要
在前面的文章中有分析過關系型數據庫的連接,以及連接池的原理。在mongo數據庫同樣存在,經常看到有網友在問mongo 連接了數據庫要不要關,怎么關。內置的數據庫連接池是單線程還是多線程,mongo服務器為什么會殺游標,殺連接諸如此類的問題,其實這類問題基本上就是連接池的問題,而很多和關系型數據庫是類似的,并不是mongo獨有的。
本文旨在梳理這些問題,進行一個全面的分析。
客戶端連接通過driver jar去連接,以java為例,通過mongo-java-driver
連接mongo,這一點和關系型數據庫一樣,不同的是關系型數據庫有一套標準的阻塞型的,寫入JDK的數據庫操作實現,即JDBC。而mongo則是完全有driver提供。在mongo-java-driver 3.0版本之前只提供了同步的driver操作,3.x之后開始提供異步的driver操作,這邊不做擴散,后續會有相關博文介紹異步的數據庫操作,本文只介紹同步driver操作。
數據庫操作
一個基于mongo-java-driver-2.14.x的mongo操作流程
</>復制代碼
public static void main(final String[] args) {
try {
final String host = "localhost";
// 連接配置屬性
final MongoClientOptions clientOptions = new MongoClientOptions.Builder()
.writeConcern(WriteConcern.ACKNOWLEDGED)
.readPreference(ReadPreference.secondaryPreferred())
.connectionsPerHost(10).socketTimeout(5000).build();
final List credentialsList = new ArrayList();
final String str = "test";
final char[] psd = str.toCharArray();
final MongoCredential credential = MongoCredential.createCredential("test",
"test",
psd);
credentialsList.add(credential);
final ServerAddress address = new ServerAddress(host, 27017);
//包含了一個內置的數據庫連接池
final MongoClient client = new MongoClient(address, credentialsList, clientOptions);
final DB db = client.getDB("test");
final DBCollection postCollection = db.getCollection("test");
postCollection.findOne();
//連接關閉,釋放資源
client.close();
} catch (final UnknownHostException e) {
e.printStackTrace();
}
}
這只是一個sample 實際應用中,MongoClient在一個jvm中只應該有一個實例,由他管理連接,進行數據庫操作。
client與數據庫的交互,mongo 協議也是基于TCP的
幾個重要的類
MongoClientOptions: 數據庫連接配置項
DB: database連接
DBCollection: collection操作
所以mongo連接的配置核心就在于MongolientOptions類了。比較重要的配置就是
connectionsPerHost,對于線上環境,如果連接數據庫的應用比較多,這個連接數不宜過大
socketTimeout: 數據庫操作超時時間,一般5s中,對于慢操作,不應該一直占用連接,會損害應用性能,阻塞其他操作
</>復制代碼
private int minConnectionsPerHost; //每個節點的最小連接數
</>復制代碼
private int connectionsPerHost = 100; // 每個節點的連接數
private int threadsAllowedToBlockForConnectionMultiplier = 5; //最大等待線程
private int maxWaitTime = 1000 * 60 * 2; // 獲取連接最大等待時間
private int maxConnectionIdleTime; // 連接池最大空閑時間
private int maxConnectionLifeTime;
private int connectTimeout = 1000 * 10; // 連接最大時間
private int socketTimeout = 0; // 操作最大時間
private boolean socketKeepAlive = false;
private boolean autoConnectRetry = false;
private long maxAutoConnectRetryTime = 0;
// 心跳檢測,保持TCP連接
private int heartbeatFrequency = Integer.parseInt(System.getProperty("com.mongodb.updaterIntervalMS", "5000"));
private int minHeartbeatFrequency = Integer.parseInt(System.getProperty("com.mongodb.updaterIntervalNoMasterMS", "500"));
private int heartbeatConnectTimeout = Integer.parseInt(System.getProperty("com.mongodb.updaterConnectTimeoutMS", "20000"));
private int heartbeatSocketTimeout = Integer.parseInt(System.getProperty("com.mongodb.updaterSocketTimeoutMS", "20000"));
可以和關系型數據庫連接池的實現對比一下
</>復制代碼
initialSize:初始連接數
maxActive: 最大連接數量
minIdle: 最小連接數量
maxWait: 獲取連接最大等待時間ms
minEvictableIdleTimeMillis:連接保持空閑而不被驅逐的最小時間
timeBetweenEvictionRunsMillis:銷毀線程的時間檢測
testOnBorrow:申請連接時執行,比較影響性能
validationQuery:testOnBorrow為true檢測是否是有效連接sql
testWhileIdle:申請連接的時候檢測
mongo 內置的連接池管理比較簡單,沒有進行連接池的連接有效管理,通過heartbeat間隔一段時間發送數據包給mongo 服務器,確保連接有效,這一點和之前介紹的有點區別,之前的銷毀掉無用的連接。這樣會增加額外的網絡和CPU負擔。
看下mongo 創建MongoClient的時候會去初始化連接池。等到進行數據庫操作的時候,再去PooledConnectionProvider中獲取一個連接,進行操作
通過以上分析,對于mongo driver 3.x 以下的mongo數據庫連接池與關系型數據庫連接池并無區別。只是連接池的實現方式不一樣,比如一個用鎖,一個用信號量。容器的選型也不太一樣,但是這些并不會影響到大部分的應用開發者對于連接的配置和理解。回到開頭提出的幾個問題,看到這里自然就有答案了。而對于服務器kill掉游標這個問題,游標本身也不是mongo獨有的,客戶端通過游標控制結果數量的讀取,游標本身也是占用不少資源的,所以不能一直占有,服務器kill掉游標,所以游標占用時間太長。可以通過db.serverStatus().metrics.cursor去查看timeout的游標,找出耗時操作,進行優化。
</>復制代碼
"cursor": {
"timedOut": "NumberLong(99)"
"open": {
"noTimeout": "NumberLong(0)"
"pinned": "NumberLong(3)"
"total": "NumberLong(3)"
}
}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/19259.html
摘要:推薦閱讀資源庫工具應用程序精選列表中文版有哪些鮮為人知,但是很有意思的網站一份攻城獅筆記每天搜集上優秀的項目一些有趣的民間故事超好用的谷歌瀏覽器油猴插件合集目錄資源文檔文章圖書會談教程更多庫工具管理數據部署桌面發展監控應用資源文檔介紹文檔教 推薦閱讀 MongoDB 資源、庫、工具、應用程序精選列表中文版 有哪些鮮為人知,但是很有意思的網站? 一份攻城獅筆記 每天搜集 Github ...
摘要:出現的問題筆者前段時間開發一個新項目的某個功能模塊要讀取老游戲中某個數據庫計作庫連續讀庫中的個集合相當于的張表取數據在測試環境單次操作時是內但是并發測試情況下比如內個并發時讀取庫個集合的耗時能達到以上甚至且個并發請求幾乎同時完成但是在我本地 出現的問題 筆者前段時間開發一個新項目的某個功能模塊,要讀取老游戲中某個Mongo數據庫(計作A庫),連續讀A庫中的6個集合(相當于MySQL的6...
摘要:簡介在我的前一篇小文中小書提到了可以更換會話儲存那么這篇文章我們就來講講在進行會話管理的時候如何將會話數據保存在外部數據庫中本文中我們使用用作會話儲存數據庫本文中使用的模塊以及版本號一覽模塊名稱版本號特性支持支持所有版本的支持支持 簡介 在我的前一篇小文中express-session小書提到了express-session可以更換會話儲存. 那么這篇文章我們就來講講express在進...
摘要:簡介在我的前一篇小文中小書提到了可以更換會話儲存那么這篇文章我們就來講講在進行會話管理的時候如何將會話數據保存在外部數據庫中本文中我們使用用作會話儲存數據庫本文中使用的模塊以及版本號一覽模塊名稱版本號特性支持支持所有版本的支持支持 簡介 在我的前一篇小文中express-session小書提到了express-session可以更換會話儲存. 那么這篇文章我們就來講講express在進...
閱讀 2324·2021-11-08 13:13
閱讀 1257·2021-10-09 09:41
閱讀 1701·2021-09-02 15:40
閱讀 3195·2021-08-17 10:13
閱讀 2558·2019-08-29 16:33
閱讀 3135·2019-08-29 13:17
閱讀 3145·2019-08-29 11:00
閱讀 3306·2019-08-26 13:40