2012-01-14 6 views
8

現在、MongoDBとMySQLを実際のサンプルデータで使用する際のワークフローと効率を比較するために、個人的なテストとベンチマークを行っています。PHPの16000 Mongo DBインスタンスの開閉

各データベースに自分のデータをセットアップするために、私は数千のループを行い、データオブジェクトをランダムに作成してデータベースに挿入します。

しかし私は解決できないPHPでMongoクラスを使用していくつかの問題を抱えています。問題はそうです:

新しいMongoインスタンスと接続を作成し、小さな配列をコレクションに挿入してから接続を閉じるループがあります。このループは20000回実行する必要があります。しかし、インスタンスの作成/接続を試みると、16300ndループ(16200分、最大数16350)が失敗することがあります。

ループ内のコードは、以下である:単純な連想配列を返す()

$data = get_random_user_data(); 

$mongo = new Mongo('mongodb://admin:[email protected]:27017/test'); 

    if ($mongo->test->users->insert($data)) { 
     $users[] = array('id' => $data['_id'], 'name' => $data['username']); 
    echo $i." - Added user: ".$data['username'].'<br/>'; 
    } 

$mongo->close(); 

get_random_user_data。

私が手にエラーがある:行で

Fatal error: Uncaught exception 'MongoConnectionException' with message 'Unknown error' 

$mongo = new Mongo('mongodb://admin:[email protected]:27017/test'); 

任意のアイデア?何らかのセキュリティやスパム防止のような、基本的なものがありますか?

ありがとうございます。

追加情報:

スクリプトを約114.9797秒で死にます。 PHPのメモリや時間ベースの問題ではないので、MySQLのベンチマークでは、問題なく約1200時間(開いている接続、挿入、閉じている接続をループする同じ方法で)昨日挿入しました。

のphpinfoモンゴ情報

PHPバージョン5.3.5

の実行:

MongoDB Support enabled 
Version 1.2.0- 
Directive Local Value Master Value 
mongo.allow_empty_keys 0 0 
mongo.allow_persistent 1 1 
mongo.auto_reconnect 1 1 
mongo.chunk_size 262144 262144 
mongo.cmd $ $ 
mongo.default_host localhost localhost 
mongo.default_port 27017 27017 
mongo.long_as_object 0 0 
mongo.native_long 0 0 
mongo.no_id 0 0 
mongo.utf8 1 1 
+1

うん、面白いです。あなたは接続を再利用できますか?おそらくそれはプロセスごとのことですか? Pythonで同じことをしようとするとどうなりますか? MongoDBソース(および/またはPHPドライバ)を '不明なエラー'のために拝見しましたか?あなたは接続の間に少し寝る場合はどうなりますか? – Cameron

+0

実際に接続を再利用することはできません。これはベンチマークに含めることです。このコメントの時点で、誰かがRubyドライバで同じ問題を抱えていると言いました。ソースにはまったく目を向けていないが、私がチャンスを取ったときはいつもそうするだろう。返信いただきありがとうございます。 :) – Chrisui

+0

私はベンチマークについて理解していますが、これは問題の原因となっている多くの接続(おそらくRameshの答えが出ているようです)が – Cameron

答えて

6

オペレーティングシステムには、開こうとするソケットの数が限られています。あなたがソケットを開いてそれを閉じると、OSは即座にそれを "利用可能な"プールに戻すわけではなく、Natがin his answerと書いている「時間待機」状態でしばらくはハングアップします。

OSが開くソケットの数を増やすことができます。http://www.mongodb.org/display/DOCS/Too+Many+Open+Files(各ソケットは開いた「ファイル」です)を参照してください。

また、かなり古いバージョンのドライバを使用しているため、アップグレードを検討することをお勧めします。

+0

助けてくれてありがとう! – Chrisui

3

は、私は、これはあまりにもルビードライバから同じ動作であることを確認してください。私はruby mongoと同様のケースを複製しました。ruby mongoは毎回mongoインスタンスを開閉することで20000レコードを挿入します。これはエラーメッセージです

14200に14110の間で、それは@Chrisuiは私も経験しておりません、言ったように、これはまた、完全なスタックトレース

Failed to connect to host localhost and port 27017: Cannot assign requested address - connect(2) 
["/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/util/pool.rb:171:in `rescue in checkout_new_socket'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/util/pool.rb:166:in `checkout_new_socket'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/util/pool.rb:267:in `block (2 levels) in checkout'", "<internal:prelude>:10:in `synchronize'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/util/pool.rb:259:in `block in checkout'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/util/pool.rb:252:in `loop'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/util/pool.rb:252:in `checkout'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/connection.rb:496:in `checkout_writer'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/networking.rb:34:in `send_message'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/collection.rb:948:in `block in insert_documents'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/util/logging.rb:28:in `instrument'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/collection.rb:944:in `insert_documents'", "/home/ramesh/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.5.2/lib/mongo/collection.rb:343:in `insert'", "/home/ramesh/Desktop/load_test.rb:15:in `block in load_test'", "/home/ramesh/Desktop/load_test.rb:6:in `times'", "/home/ramesh/Desktop/load_test.rb:6:in `load_test'", "(irb):2:in `irb_binding'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/workspace.rb:80:in `eval'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/workspace.rb:80:in `evaluate'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/context.rb:254:in `evaluate'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb.rb:159:in `block (2 levels) in eval_input'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb.rb:273:in `signal_status'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb.rb:156:in `block in eval_input'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/ruby-lex.rb:243:in `block (2 levels) in each_top_level_statement'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `loop'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `block in each_top_level_statement'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `catch'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `each_top_level_statement'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb.rb:155:in `eval_input'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb.rb:70:in `block in start'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb.rb:69:in `catch'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/irb.rb:69:in `start'", "/home/ramesh/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'"] 
ArgumentError: uncaught throw #<Mongo::ConnectionFailure: Failed to connect to host localhost and port 27017: Cannot assign requested address - connect(2)> 
    from /home/ramesh/Desktop/load_test.rb:21:in `throw' 
    from /home/ramesh/Desktop/load_test.rb:21:in `rescue in block in load_test' 
    from /home/ramesh/Desktop/load_test.rb:7:in `block in load_test' 
    from /home/ramesh/Desktop/load_test.rb:6:in `times' 
    from /home/ramesh/Desktop/load_test.rb:6:in `load_test' 

ある

uncaught throw #<Mongo::ConnectionFailure: Failed to connect to host localhost and port 27017: Cannot assign requested address - connect(2)> 

失敗に保ちます任意のメモリが低下します。

これは私があなたのベンチマークは意味がありません

require 'mongo' 

def load_test 
    start = Time.now 
    puts 'starting at :' + start.to_s 
    20000.times do |i|  
      begin 
       puts i  
      doc = {"name" => "MongoDB", "type" => "database", "count" => 1,"info" => {"x" => 203, "y" => '102'}} 
      con = Mongo::Connection.new("localhost") 
      db = con['bulktest'] 
      coll = db['test'] 
      coll.insert(doc) 
      con.close 
       con,db,coll=nil,nil,nil 
     rescue Exception => e 
      puts e.message 
      puts e.backtrace.inspect 
      throw e 
     end 

    end 
    stop = Time.now 
    puts 'stoping at :' + stop.to_s 
    puts 'elapsed time is ' + (stop-start).to_s + ' seconds' 
end 
1

を試してみましたスクリプトです。開閉はしないでください。毎回開閉する代わりに持続的な接続を再利用する必要があります。すぐにソケットを開いて閉じると、ファイルディスクリプタを使用しているタイムアウト状態のソケットが多すぎる

+0

それは意味をなさない。全体的なアイデアは、接続を開いて何かをして終了するのにかかる時間をベンチマークすることです。つまりクイックリクエストを何千回も複製する。あなたはこの「タイムスタンバイ状態」をもっと説明してください。 – Chrisui

+0

チェックアウトhttp://stackoverflow.com/questions/1803566/what-is-the-cost-of-many-time-wait-on-the-server-side – Nat