在Ruby的MongoDB2.4.3驅動版本中,通過創建一個Mongo::Client對象來構建一個Ruby的數據庫連接。Mongo::Client構造器提供兩種構造方式:一是通過提供主機列表和一些可選參數,另外還有通過一個連接URI。創建好的數據庫連接默認連接到admin數據庫。
1.使用Mongo::Client創建數據庫客戶端連接
1.1. 單服務器模式創建數據庫連接
在單服務器模式下創建數據庫連接,只需提供一個主機連接參數。另外,還可以通過消除自動發現步驟強制將集羣拓撲轉換爲單機模式。可以通過下述三種方式創建單服務器模式下的數據庫連接
Mongo::Client.new(['127.0.0.1:27017'],:database=>'mydb')
Mongo::Client.new(['127.0.0.1:27017'],:database=>'mydb',:connect=>:direct)
Mongo::Client.new('mongodb://127.0.0.1:27017/mydb')
1.2. 副本集模式創建數據庫連接
通過傳遞一個或多個主機地址參數和副本集名字,可以創建一個到副本集的數據庫連接。即使在創建時沒有完全提供副本集的所有信息,MongoDB的驅動器的自動探索模式可以找到副本集中的所有成員。創建副本集中的數據庫連接可以通過下面的形式創建:
Mongo::Client.new(['127.0.0.1:27017','127.0.0.1:27018'],:database=>'mydb',:replica_set=>'myapp')
Mongo::Client.new('mongdb://127.0.0.1:27017,127.0.0.1:27018/mydb?replicaSet=myapp')
1.3. 共享集羣模式創建數據庫連接
通過傳遞一個或多的Mongos 主機,來創建一個共享集羣模式。自動探索模式可以限定服務器是mongos實例,但如果你關閉了自動探索模式,就要將shared參數傳遞到連接中來實現集羣模式數據庫連接的創建。通過以下三種例子可以創建數據庫連接:
Mongo::Client.new(['127.0.0.1:27017'],:database=>'mydb')
Mongo::Client.new(['127.0.0.1:27017'],:database=>'mydb',:connect=>:shared)
Mongo::Client.new('mongodb://127.0.0.1:27017/mydb?connect=shared')
2. 數據庫客戶端連接參數選項
在使用Mongo::Client時,可以通過多個不同的可選參數來配置驅動的行爲,可以通過在構造器中配置這些參數或者將它們通過URI提供給Mongo::Client.
鑑於URI的參數設置方式需要使用駝峯格式,這不是Ruby的標準格式。下面的表格中列出了URI格式的參數配置選項,以及相對應的使用Ruby構造器的參數選項。使用上述兩種參數設置方式時需要注意URI參數設置中的選項時間單位是毫秒,而在Ruby構造器中對應的是float類型的秒。
3. URI參數及對應Ruby參數
URI選項 | Ruby選項 |
replicaSet=String | :replica_set=>String |
connect=String | :connect=>Symbol |
ssl=Boolean | :ssl=>true|false |
connectTimeoutMS=Integer | :connect_timeout=>Float |
socketTimeoutMS=Integer | :socket_timeout=>Float |
serverSelectionTimeoutMS=Integer | :server_selection_timeout=>Float |
localThresholdMS=Integer | :local_threshold=>Float |
maxPoolSize=Integer | :max_pool_size=>Integer |
minPoolSize=Integer | :min_pool_size=>Integer |
waitQueueTimeoutMS=Integer | :wait_queue_timeout=>Float |
w=Integer|String | { :write=>{:w=>Integer|String}} |
wtimeoutMS=Integer | { :write=>{:wtimeout=>Float}} |
journal=Boolean | { :write=>{:j=>true|false}} |
fsync=Boolean | { :write =>{:fsync=>true|false}} |
readPreference=String | { :read=>{:mode=>Symbol}} |
readPreferenceTags=String | { :read=>{:tag_sets=>Array<String> }} |
authSource=String | :auth_source=>String |
authMechanism=String | :auth_meth=>Symbol |
authMechanismProperties=Strings | { :auth_mech_properties=>{:service_realm=>String ,:canonicalize_host_name=>true|false,:service_name=>String}} |
4. 下面會詳細講解Ruby中每個選項的作用,默認值和類型
參數 | 參數描述 | 參數類型 | 默認值 |
:replica_set | 當使用副本集模式時,該參數用於設置副本集的名字,且可以在啓用自動探索模式時通過名字過濾服務器 | String | none |
:ssl | 通知客戶端通過SSL連接到服務器 | Boolean | false |
:ssl_cert | 用於設置證書文件路徑,該證書用於識別鑑定到MongoDB連接是否有效。如果設置了該選項,將會比:ssl_cret_string的值和:ssl_sret_object的值具有更高的使用優先級 | String | none |
:ssl_cert_string | 該string字段包含了使用PEM編碼的用於鑑別連接有效性的證書信息。如果設置了該參數,它比:ssl_cret_object的值具有更高的使用優先級 | String | none |
:ssl_cert_object | 使用OpenSSL::X509::Certificate證書鑑別到MongoDB的連接 | OpenSSL::X509: :Certificate | none |
:ssl_key | 鑑別連接有效性的私鑰文件。雖然祕鑰文件與證書存儲在同一個文件,但是兩個需要被精確匹配。如果設置了該參數,它比:ssl_key_string和:ssl_key_object具有更高的使用優先級 | String | none |
:ssl_key_string | 包含用於鑑別連接有效性的使用PEM編碼的私鑰字符串信息。如果設置了這個參數,它比:ssl_key_object具有更高的使用優先級 | String | none |
:ssl_key_object | 鑑別連接有效性的私鑰對象 | OpenSSL::PKey | none |
:ssl_key_pass_phrase | 私鑰的密碼信息 | String | none |
:ssl_ca_cert | 一組把授權證書連接起來的證書信息的存儲路徑 ,這些授權證書用於從連接的另一端驗證證書是 否通過。參數:ssl_verfiy的使用需要設置 :ssl_ca_cret,:ssl_ca_cret_string, :ssl_ca_cret_object三個參數中的一個。 | String | none |
:ssl_ca_cert_string | 包含一組把授權證書連接起來的證書信息的字符串 ,這些授權證書用於從連接的另一端驗證證書是否 通過。參數:ssl_verfiy的使用需要 設置:ssl_ca_cret,:ssl_ca_cret_string, :ssl_ca_cret_object三個參數中的一個。 | String | none |
:ssl_ca_cert_object | 代表了把授權證書連接起來的證書信息的OpenSSL::X509::Certificate數組,這 些授權證書用於從連接的另一端驗證證書會否通過。參數:ssl_verfiy的使用需要設置:ssl_ca_cret,:ssl_ca_cret_string,:ssl_ca_cret_object三個參數中的一個。 | Array<OpenSSL::X509:: Certificate> | none |
:ssl_verify | 用於設置是否進行對等證書驗證 | Boolean | false |
:connect_timeout | 創建一個socket連接,拋出異常之前的等待時間(秒) | Float | 10秒 |
:socket_timeout | 在一個socket執行操作拋出異常之前的等待時間(秒) | Float | 5秒 |
:max_pool_size | 單個服務器的連接池的最大連接數 | Integer | 5 |
:min_pool_size | 單個服務器的連接池的最小連接數 | Integer | 1 |
:wait_queue_timeout | 等待連接池中連接變爲有效狀態的等待時間 | Float | 1 |
:write | 具體設置與寫相關的Hash類型的參數。其值可以爲:w,:wtimeout,:j,:fsync 如{ :write =>{ :w=>2}} | Hash | {:w=>1} |
:read | Hash類型的參數,用於具體設置首選讀 模式以及對於選定服務器的標籤集合。 其值可以設置爲:mode和:tag_sets。 例如{ :read=>{ :mode=>secondary, :tag_sets=>["berlin"]}} | Hash | {:mode =>:primary} |
:auth_source | 具體設置了授權源信息 | String | 2.6及其之後版本,如果提供了授權證書,則默認爲admin;否則的話就是當前的數據庫 |
:auth_mech | 具體設置使用的授權機制 。可以是下述值的其中之一::mongodb_cr,:mongodb_x509,:plain,:scram | Symbol | MongoDB3.0後的版本,如果用戶提供了資格證書但是又沒有設置:auth_mech屬性,則默認爲:scram。2.6版本之前,默認爲:mongodb_cr |
:auth_mech_ properties | 提供了額外的授權機制屬性 | Hash | none |
:user | 認證使用的用戶名稱 | String | none |
:password | 認證使用的用戶密碼 | String | none |
:connect | 覆蓋驅動的自動探索特性,並且強制將集羣拓撲結構轉變爲一個特定的類型。包括::direct,:replica_set或者:shared | Symbol | none |
:heartbeat_ frequency | 多個監視器異步刷新服務器狀態的時間(秒) | Float | 30 |
:database | 需要連接的數據庫名字 | String | admin |
:server_selection_ timeout | 選定一個合適的服務器去執行某些操作,在拋出異常之前的等待時間 | Float | 30 |
:local_threshold | 設置了最近的服務器和可以被選中的服務器之間切換的最大延遲時間 | Float | 0.015 |
5. 超時相關參數的設置細節
5.1連接超時:
在初始化到服務器的連接時,該參數是用來設置在拋出連接異常之前的等待時間。這個超時參數也被用來設置監視器ping它們服務器的等待時間。默認值是10秒
5.2套接字超時 socket-timeout
進行套接字操作時拋出異常之前的等待時間。這個時間的設置需要考慮網絡延時和炒作間隔。默認值沒有值,默認值是正無窮大。由於scoket_timeout設置不會停止服務器上的操作,即使超過了socket_timeout的時間,一個需要長時間運行的操作也會繼續在服務器上運行。因此我們在使用時一般使用每秒max_time_ms代替。
5.3服務器選擇超時server_selection_timeout
數據庫驅動選擇合適的服務器開展操作時,拋出異常之前的等待時間,默認值30s。該值設置時需要考慮故障轉移時選舉服務器選舉的速度。
5.4本地延遲local_threshold
最近的服務器和被認爲可進行操作的服務器之間的最大延時。默認值0.015。注意區分一下,
注意:該值不是驅動和服務器之間的延遲窗口,而是最近的服務器和其他服務器之間的延遲。
5.5 排隊等待超時時間 wait_queue_timeout
等待連接池中的連接可用的等待時間。當出現下述兩種場景時:一是在多線程應用場景下出現多個超時的錯誤,還有就是當操作佔用時間較長,我們需要考慮增加該值。默認值是1s。
5.6 最大連接池大小 max_pool_size
單個服務器的連接池最大的連接數,默認爲5
5.7 最小的連接池大小
單個服務器的連接池最小的連接數,增加這個值可以提高初始化時池中可用的連接數,減少後續創建新連接的開銷。默認大小1.
5.8 max_time_ms
用於具體化設置一個特定操作的參數,它定義了在一個遊標上處理操作的累計總時間限制。如果想要服務器上的操作可以被中斷,請使用該參數來代替socket_timeout參數設置。
注意:socket_timeout和max_time_ms的區別是,超過設定時間後,後者會中斷服務器上的操作
6. 連接池細節
在MongoDB的拓撲結構中,Mongo::Client實例有一個單服務器上連接池的屬性。當你的應用需要操作多個並行的MongoDB連接時,連接池就會爲其提供服務。沒有線程相關的連接。
MongoDB的拓撲結構中每臺服務器上還預留了一個額外的用於監控服務器狀態的連接。使用屬性max_pool_size來設定每個連接池的大小被,默認值是5。當你的應用中一個線程開始操作MongoDB數據庫時,它會嘗試從連接池中獲取到一個數據庫連接供後續操作使用。如果池中存在多個可用空閒連接,它會從池中挑選出一個連接並且用該連接來進行數據庫操作。如果當前池中無可用連接,並且池中的連接數小於max_pool_size,就會創建一個新的連接。如果池中所有連接均不可用,且池的大小已達到最大值,該線程會等待池中的被其他線程佔用的連接被釋放返回。
線程的等待時間也是可配置的。使用wait_queue_timeout,時間單位爲秒。該參數確定了當連接池中午可用連接時,一個線程等待連接被返回到池中變爲可用連接的等待時間。如果等待時間到了,就會拋出Timeout::Error錯誤。默認值爲1s。
你可以使用min_pool_size來設置連接池初始化時池中的連接數目。如果你的應用會面臨尖峯負荷,而且你想避免尖峯負荷時創建新連接的延遲,設置這個參數會有所幫助。默認值是1.
下面講述一個實例,爲多線程應用創建一定數目的連接:一個客戶端連接到一個3節點的副本集而且打開了3個監控sockets,而且也爲應用打開了支持其多線程場景的並行連接操作多個sockets連接,連接數最大不超過max_pool_size。如果應用了僅僅連接到primary節點(默認),這樣只會有primary節點的連接增長了且最大值爲8(5個到primary節點連接池的連接+3個監控連接)。如果應用的偏好讀取方式是查詢secondary節點,那麼secondary節點的連接池也會增大,並達到最大值18(5+5+5+3)。
默認的Mongo::Client配置方式適用於絕大多數應用場景:
client=Mongo:Client.new(["localhost:27017"])
每個處理創建一個client連接,在所有的後續操作中重用這個client。爲每個請求創建一個client連接是一個共性的錯誤,這種配置方式是非常低效的而且這也違背了client的設計原則。
爲了支持但處理步驟中的極端並行MongoDB連接,我們需要增加max_pool_size參數值大小:
client=Mongo::Client.new(["localhost:27017"],:max_pool_size=>200)
任意數據的線程都可以等待連接變爲可用,它們的等待時間(默認1s)可以通過wait_queue_timeout設置。:
client=Mongo::Client.new(["localhost:27017"],:wait_queue_timeout=>0.5)
當使用任意線程在client上調用close方法,所有的連接都會被關閉。
下一節繼續講解Ruby MongoDB的進階,CRUD操作。