MongoDB 3.2.9 關於安全認證後使用C#調用碰上的相關問題

因爲項目須要MongoDB作爲存儲數據庫,在學習過程碰上疑難雜症,心痛如海,故此終於開始書寫博客之路。html

 

操做MongoDB類庫版本:mongodb

----------------------------------------------shell

MongoDB.Driver 2.3 
MongoDB.Driver.Core 2.3
MongoDB.Bson 2.3

MongoDB 版本 3.2.9

參考相關學習連接(轉載):
---------------------------------------------
https://izk.cloud/437/  安全認證,權限管理
http://www.cnblogs.com/huangxincheng/archive/2015/10/12/4870557.html 主從熱備集羣

http://blog.csdn.net/luonanqin/article/details/8497860 集羣搭建

鏈接字符串的相關變化:數據庫

-----------------------------------------------安全

沒有安全認證的URL:mongodb://127.0.0.1:27017架構

加上安全認證的URL:mongodb://[userName]:[userPwd]@127.0.0.1:27017/[DataBaseName]dom

重點變化是最後一個指定數據庫,若是不指定,將爲默認數據庫post

因此想固然測試的時候通常使用的是mongodb://[userName]:[userPwd]@127.0.0.1:27017學習

並無加上自定義數據庫名稱,致使初始化報錯。測試

網上參考文章帶安全驗證的鏈接都是:mongodb://[userName]:[userPwd]@127.0.0.1:27017

都沒有在最後補上/[DataBaseName]  致使自定義數據庫的建立失敗。

 

主副熱備集羣相關代碼處理上的問題:

-------------------------------------------------

 感謝國慶,感謝國家,感謝這二篇博文,一直在操做主副集羣C#代碼碰上未知報錯,經過下面連接

深度學習了一下:

雙十一來了,別讓你的mongodb宕機了

MongoDB副本集學習(二):基本測試與應用

雖然依然沒有解決個人問題,可是從中學習到經驗,值得回報。

按照上面代碼(轉載):

MongoClientSettings set = new MongoClientSettings();
List<MongoServerAddress> servers = new List<MongoServerAddress>();
servers.Add(new MongoServerAddress("192.168.129.129", 37017));
servers.Add(new MongoServerAddress("192.168.129.129", 37018));
servers.Add(new MongoServerAddress("192.168.129.129", 37019));
set.Servers = servers;

//設置副本集名稱
set.ReplicaSetName = "rs0";
//設置超時時間爲3秒
set.ConnectTimeout = new TimeSpan(0, 0, 0, 3, 0);


MongoClient client = new MongoClient(set);
MongoServer server = client.GetServer();
MongoDatabase db = server.GetDatabase("test");
MongoCollection coll = db.GetCollection("test");

//插入
BsonDocument bd = new BsonDocument();
bd.Add("name", "zhanjindong");
bd.Add("age", 23);
bd.Add("sex", "男D");

coll.Insert(bd);

//讀取
QueryDocument qd = new QueryDocument();
qd.Add("name", "zhanjindong");
qd.Add("age", 23);
qd.Add("sex", "男D");

BsonDocument rd = coll.FindOneAs<BsonDocument>(qd);

Console.WriteLine(rd.ToString());

 

 

默認的C#驅動的ReadPreference是Primary,也就是說讀寫操做都是在主節點上的,那麼當集羣中只剩下一個節點的時候,按照前面所說該節點必定是secondary節點,這樣讀取操做也是無法進行的(經過mongo shell固然是能夠的)。解決方法就是設置驅動的ReadPreferenceMode:

set.ReadPreference = new ReadPreference(ReadPreferenceMode.PrimaryPreferred);

狀態說明:
primary
主節點,默認模式,讀操做只在主節點,若是主節點不可用,報錯或者拋出異常。
primaryPreferred
首選主節點,大多狀況下讀操做在主節點,若是主節點不可用,如故障轉移,讀操做在從節點。
secondary
從節點,讀操做只在從節點, 若是從節點不可用,報錯或者拋出異常。
secondaryPreferred
首選從節點,大多狀況下讀操做在從節點,特殊狀況(如單主節點架構)讀操做在主節點。
nearest
最鄰近節點,讀操做在最鄰近的成員,多是主節點或者從節點

 

你覺得上面就複製粘貼一下就解決了?No,實際調用跟參考代碼是二回事,呃?繞回正題,經過上面代碼覺得能夠輕鬆一步了,結果又挖了一個大坑,在招待我。

 

報錯詳情:

System.TimeoutException」類型的異常在 MongoDB.Driver.Core.dll中發生,但未在用戶代碼中進行處理其餘信息: A timeout occured after 3000ms selecting a server using CompositeServerSelector {
    Selectors = ReadPreferenceServerSelector {
        ReadPreference = {
            Mode = Secondary, TagSets = []
        }
    }, LatencyLimitingServerSelector {
        AllowedLatencyRange = 00: 00: 00.0150000
    }
}.Client view of cluster state is {
    ClusterId: "1",
    ConnectionMode: "ReplicaSet",
    Type: "ReplicaSet",
    State: "Disconnected",
    Servers: [{
        ServerId: "{ ClusterId : 1, EndPoint : "
        Unspecified / mongodb - 10.localdomain: 27017 " }",
        EndPoint: "Unspecified/mongodb-10.localdomain:27017",
        State: "Disconnected",
        Type: "Unknown",
        HeartbeatException: "MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server. ---> System.Net.Sockets.SocketException: 不知道這樣的主機。

 

我當時就#¥#@¥@#¥,你懂的,一波三折,要命,通過大量時間排查我鎖定問題位置:

 EndPoint: "Unspecified/mongodb-10.localdomain:27017",

底氣何來?緣由以下:

若是你也是本地測試而且副集羣IP地址使用是域名綁定,那麼你在HOSTS沒有配置域名的狀況下,就會出現上面的超時30秒錯誤(一想起無數個F5等30秒就。。。。)

 

接下來配置HOSTS文件:

而後燒香拜佛,果真不出所料,調用成功,爲此付出很多冤枉路,若是有人碰上相同的問題,能夠參與一下。

最後放上測試單元代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System.Linq.Expressions;

public class MongoUnitily
{
    /// <summary>
    /// MongoDB調用類
    /// </summary>
    private MongoUnitily()
    {
        dataBase = new MongoClient(new MongoClientSettings
        {
            Credentials = new List<MongoCredential>() {
               MongoCredential.CreateCredential("avatar","*******","*********")  // 數據庫名稱,用戶名,用戶密碼
            },
            Servers = new string[] { "10.199.*.1", "10.199.*.2", "10.199.*.3" }.Select(x => { return new MongoServerAddress(x); }), // 集羣IP地址
            ConnectionMode = ConnectionMode.ReplicaSet,                                         // Replica 模式
            ReplicaSetName = "RS01",                                                       // Replica名稱
            ReadPreference = new ReadPreference(ReadPreferenceMode.SecondaryPreferred),         // 讀寫配置,副IP不起做用的狀況下使用主IP
            ConnectTimeout = new TimeSpan(0, 0, 0, 3, 0),                                       // 3秒報錯測試,當初30秒我是等閒人。。。。
            MaxConnectionIdleTime = new TimeSpan(0, 0, 0, 3, 0),                                // 3秒報錯測試,當初30秒我是等閒人。。。。
            MaxConnectionLifeTime = new TimeSpan(0, 0, 0, 3, 0),                                // 3秒報錯測試,當初30秒我是等閒人。。。。
            ServerSelectionTimeout = new TimeSpan(0, 0, 0, 3, 0)                                // 3秒報錯測試,當初30秒我是等閒人。。。。
        }).GetDatabase(database);                                                               // 經過數據庫名稱獲取 DbBase
    }

    static MongoUnitily()
    {
        //初始化單例對象
        Instance = new MongoUnitily();

    }
    /// <summary>
    /// 數據庫名稱
    /// </summary>
    private string database = "avatar";//數據庫名
      /// <summary>
      /// dataBase上下文對象
      /// </summary>
    private IMongoDatabase dataBase = null;

    public static MongoUnitily Instance { get; private set; }

    /// <summary>
    /// 驗證讀取
    /// </summary>
    /// <returns></returns>
    public bool IsGet()
    {
        bool result = true;
        var coll = dataBase.GetCollection<SysCodes>(nameof(SysCodes));
        Expression<Func<SysCodes, bool>> predicate = x => true;
        try
        {
            var count = coll.Find(predicate).Count();
        }
        catch
        {
            result = false;
        }
        return result;
    }

    /// <summary>
    /// 驗證寫
    /// </summary>
    /// <returns></returns>
    public bool IsPost()
    {
        var result = true;
        var coll = dataBase.GetCollection<Demo>(nameof(Demo));
        try
        {
            coll.InsertOne(new Demo { Id = Guid.NewGuid(), Name = "" });
        }
        catch
        {
            result = false;
        }
        return result;
    }
    /// <summary>
    /// 測試類
    /// </summary>
    public class Demo
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
}

 

 

 驗證結果:

 

 本篇文章旨在解決使用新版本MongoDB碰上的集羣、鏈接字符串、安全驗證的相關問題,文章深度不高,提供新手對象相互學習互挽。

相關文章
相關標籤/搜索