Mongo連線分析
#摘要#
在前面的文章中有分析過關係型資料庫的連線,以及連線池的原理。在mongo資料庫同樣存在,經常看到有網友在問mongo 連線了資料庫要不要關,怎麼關。內建的資料庫連線池是單執行緒還是多執行緒,mongo伺服器為什麼會殺遊標,殺連線諸如此類的問題,其實這類問題基本上就是連線池的問題,而很多和關係型資料庫是類似的,並不是mongo獨有的。
本文旨在梳理這些問題,進行一個全面的分析。
#Client 連線分析#
客戶端連線通過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<MongoCredential> credentialsList = new ArrayList<MongoCredential>();
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)"
}
}
相關文章
- python 連線 mongo 資料庫連線超時PythonGo資料庫
- 【Python】pymongo連結mongoPythonGo
- DBCP連線池原理分析
- ServiceStack.Redis的原始碼分析(連線與連線池)Redis原始碼
- 【Mongo】mongo聚合操作Go
- MYSQL 連線登入過程分析MySql
- SSL連線建立過程分析(1)
- 關於mysql連線慢的分析.MySql
- Oracle 表連線方式分析(精讀)Oracle
- 【Mongo】mongo配置檔案Go
- 內連線、左連線、右連線
- 基於HiKariCP元件,分析連線池原理元件
- OkHttp 3.7原始碼分析(五)——連線池HTTP原始碼
- SOFA 原始碼分析 — 連線管理器原始碼
- MySQL伺服器連線過程分析MySql伺服器
- 用TCP連線分析TUXEDO的WS模式TCPUX模式
- 各種表連線方式對比分析
- 例項解析外連線 內連線 自連線 全連線
- SQL的四種連線:內連線 左外連線 右外連線 全連線SQL
- 異常連線之未授權連線,行為風險分析的有效實踐
- MYSQL語法:左連線、右連線、內連線、全外連線MySql
- 內連線、外連線
- 連線和半連線
- 左連線,右連線
- redis 原始碼分析:Jedis 哨兵模式連線原理Redis原始碼模式
- Oracle備庫TNS連線失敗的分析Oracle
- ORACLE表連線方式的分析與優化Oracle優化
- 深入理解SQL的四種連線-左外連線、右外連線、內連線、全連線SQL
- 【mongo】mongo 欄位型別互轉Go型別
- Oracle內連線、外連線、右外連線、全外連線小總結Oracle
- 資料庫外連線,自然連線,內連線,條件連線,等值連線關係及詳解資料庫
- Socket連線和Http連線HTTP
- 長連線和短連線
- Oracle(+)連線與Join連線Oracle
- 【SQL】表連線 --半連線SQL
- Oracle左連線,右連線Oracle
- 左連線與右連線
- 左連線和右連線