71

私は最近、GitHub の C# ドライバーを使用して MongoDB で遊んでいます (驚くほど高速です)。私がテストしている小さなシングル スレッド コンソール アプリでは、すべてが正常に機能しています。シングル スレッドで 8 秒以内に 1,000,000 のドキュメント (はい、100 万) を追加できます。forループの範囲外で接続を使用した場合にのみ、このパフォーマンスが得られます。つまり、インサートごとに接続するのではなく、インサートごとに接続を開いたままにしています。明らかにそれはわざとです。

複数のスレッドでどのように機能するかを確認するために、ノッチを上げると思いました。複数の同時リクエストで Web サイトをシミュレートする必要があるため、これを行っています。私は 15 から 50 のスレッドをスピンアップしていますが、すべてのケースで合計 150,000 のドキュメントを挿入しています。スレッドを実行させて、挿入操作ごとに新しい接続を作成すると、パフォーマンスが低下します。

明らかに、接続を共有、ロック、またはプールする方法を見つける必要があります。そこに問題があります。MongoDB への接続に関するベスト プラクティスは何ですか? アプリの存続期間中、接続を開いたままにする必要がありますか (操作ごとに TCP 接続を開いたり閉じたりするのにかなりの待ち時間があります)。

MongoDB、特に基礎となる接続について、実世界または実稼働の経験がある人はいますか?

これは、挿入操作用にロックされた静的接続を使用した私のスレッド サンプルです。Web コンテキストでのパフォーマンスと信頼性を最大化する提案を提供してください!

private static Mongo _mongo;

private static void RunMongoThreaded()
{
    _mongo = new Mongo();
    _mongo.Connect();

    var threadFinishEvents = new List<EventWaitHandle>();

    for(var i = 0; i < 50; i++)
    {
        var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset);
        threadFinishEvents.Add(threadFinish);

        var thread = new Thread(delegate()
            {
                 RunMongoThread();
                 threadFinish.Set();
            });

        thread.Start();
    }

    WaitHandle.WaitAll(threadFinishEvents.ToArray());
    _mongo.Disconnect();
}

private static void RunMongoThread()
{
    for (var i = 0; i < 3000; i++)
    {
        var db = _mongo.getDB("Sample");
        var collection = db.GetCollection("Users");
        var user = GetUser(i);
        var document = new Document();
        document["FirstName"] = user.FirstName;
        document["LastName"] = user.LastName;

        lock (_mongo) // Lock the connection - not ideal for threading, but safe and seemingly fast
        {
            collection.Insert(document);
        }
    }
}
4

6 に答える 6

136

ここでのほとんどの回答は時代遅れであり、.net ドライバーが成熟し、無数の機能が追加されたため、適用できなくなりました。

ここにある新しい 2.0 ドライバーのドキュメントを参照してください: http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/connecting/

.net ドライバーはスレッド セーフになり、接続プールを処理します。ドキュメントによると

MongoClient インスタンスは、静的変数として、またはシングルトンの有効期間を持つ IoC コンテナーのいずれかで、グローバルな場所に格納することをお勧めします。

于 2015-06-12T18:49:32.700 に答える
9

静的接続について覚えておくべきことは、それがすべてのスレッド間で共有されるということです。必要なのは、スレッドごとに 1 つの接続です。

于 2010-02-03T17:47:18.277 に答える
6

mongodb-csharp を使用する場合は、ADO 接続のように扱います。Mongo オブジェクトを作成すると、Mongo オブジェクトは、破棄されるまで所有するプールから接続を借用します。したがって、using ブロックの後、接続はプールに戻されます。Mongo オブジェクトの作成は安価で高速です。

for(var i=0;i<100;i++) 
{ 
        using(var mongo1 = new Mongo()) 
        using(var mongo2 = new Mongo()) 
        { 
                mongo1.Connect(); 
                mongo2.Connect(); 
        } 
} 

データベース ログ
02 年 6 月水曜日 20:54:21 127.0.0.1:58214 から接続を受け入れました #1 02 年 6 月
2 日
水曜日 20:54:21 127.0.0.1:58215 から接続を受け入れましたerrno:0 エラーなし 127.0.0.1:58214
水 6 月 2 20:54:21 接続終了 127.0.0.1:58214
水 6 月 2 20:54:21 MessagingPort recv() errno:0 エラーなし 127.0.0.1:58215
水 6 月 2 20:54:21 エンド接続 127.0.0.1:58215

2 つの接続しか開いていないことに注意してください。

mongodb-csharp フォーラムを使用してこれをまとめました。 http://groups.google.com/group/mongodb-csharp/browse_thread/thread/867fa78d726b1d4

于 2010-11-05T15:54:00.933 に答える
1

CSMongo は、 jLinqの開発者によって作成された MongoDB 用の C# ドライバーです。サンプルは次のとおりです。

//create a database instance
using (MongoDatabase database = new MongoDatabase(connectionString)) {

    //create a new document to add
    MongoDocument document = new MongoDocument(new {
        name = "Hugo",
        age = 30,
        admin = false
    });

    //create entire objects with anonymous types
    document += new {
        admin = true,
        website = "http://www.hugoware.net",
        settings = new {
            color = "orange",
            highlight = "yellow",
            background = "abstract.jpg"
        }
    };

    //remove fields entirely
    document -= "languages";
    document -= new[] { "website", "settings.highlight" };

    //or even attach other documents
    MongoDocument stuff = new MongoDocument(new {
        computers = new [] { 
            "Dell XPS", 
            "Sony VAIO", 
            "Macbook Pro" 
            }
        });
    document += stuff;

    //insert the document immediately
    database.Insert("users", document);

}
于 2010-03-07T12:34:10.660 に答える
0

接続プールが答えになるはずです。

この機能は開発中です (詳細については、http://jira.mongodb.org/browse/CSHARP-9を参照してください)。

現在、Web アプリケーションのベスト プラクティスは、BeginRequest で接続し、EndRequest で接続を解放することです。しかし、私には、接続プールなしではリクエストごとに操作が高すぎると思います。そこで、グローバルな Mongo オブジェクトを用意し、それをすべてのスレッドの共有リソースとして使用することにしました (今すぐ github から最新の C# ドライバーを取得すると、同時実行のパフォーマンスも少し向上します)。

Global Mongo オブジェクトを使用することのデメリットはわかりません。したがって、別の専門家がこれについてコメントするのを待ちましょう。

でも、機能(接続プール)が完成するまでは、我慢できると思います。

于 2010-03-07T12:23:45.940 に答える
0

私はcsharp-mongodbドライバーを使用していますが、彼の接続プールでは役に立ちません:( Webリクエストごとにmongodbへのリクエストが約10〜20あります.(オンラインで150ユーザー-平均)そして、統計を監視したり接続したりすることさえできませんシェルからmongodbにすると、例外がスローされます。

リクエストごとに接続を開いて破棄するリポジトリを作成しました。私は次のようなものに依存しています:1)ドライバーには接続プールがあります2)私の調査の後(これについてユーザーグループに質問を投稿しました)-mongoオブジェクトを作成して接続を開くことは重い操作ではないことを理解しました。

しかし、今日、私の生産は停止します:(リクエストごとに開いている接続を保存する必要があるかもしれません...

ここにユーザーグループへのリンクがありますhttp://groups.google.com/group/mongodb-user/browse_thread/thread/3d4a4e6c5eb48be3#

于 2010-12-08T21:12:15.570 に答える