3

次のようなデーモン化されたrubyスクリプトをサーバーで実行しています。

@server = TCPServer.open(61101)                         
loop do                                                 
  @thr = Thread.new(@server.accept) do |sock|
    Thread.current[:myArrayOfHashes] = []   # hashes containing attributes of myObject
    SystemTimer.timeout_after(5) do
      Thread.current[:string] = sock.gets
      sock.close

      # parse the string and load the data into myArrayOfHashes

      Myobject.transaction do           # Update the myObjects Table
        Thread.current[:myArrayOfHashes].each do |h|
          Thread.current[:newMyObject] = Myobject.new
          # load up the new object with data
          Thread.current[:newMyObject].save
        end
      end

    end
  end
  @thr.join
end

このサーバーは、すべてMacOS10.6で実行されているRailsアプリケーションのデータを受信して​​管理します。クライアントは15で15分ごとにサーバーに電話をかけますが、現在15では15分ごとに電話をかけるクライアントは16ほどしかありませんが、次のことについて疑問に思っています。

  1. 2人のクライアントがほぼ同時に電話をかけた場合、1人のクライアントの接続試行は失敗しますか?
  2. サーバーが同時に収容できるクライアント接続の数を把握するにはどうすればよいですか?
  3. サーバーが使用しているメモリの量を監視するにはどうすればよいですか?

また、この種のサーバーを実装するための最良の方法について説明している記事がありますか?つまり、サーバーの複数のインスタンスを同じポートでリッスンさせることはできますか?それも役に立ちますか?

Bluepillを使用してサーバーデーモンを監視しています。

4

1 に答える 1

2

1と2
答えはノーです。互いに近くに接続している2つのクライアントは接続に失敗しません(ただし、複数のクライアントが接続に失敗する可能性があります。以下を参照してください)。

その理由は、オペレーティングシステムには、すべてのサーバーソケットに組み込まれたデフォルトのいわゆるリスニングキューがあるためです。そのため、プログラムで十分な速度で呼び出していない場合でもaccept、OSは着信接続をバッ​​ファリングし続けます。リスニングキューがいっぱいにならない限り、これらの接続をバッ​​ファリングします。

では、このキューのサイズはどのくらいですか?

ほとんどの場合、通常使用されるデフォルトのサイズは5です。サイズは、ソケットを作成しlistenてこのソケットを呼び出した後に設定されます(ここでリッスンするためのマニュアルページを参照してください)。

Rubyの場合、TCPSocket自動的に呼び出さlistenれます。Cソースコードを見ると、TCPSocket実際にサイズが5に設定されていることがわかります。

https://github.com/ruby/ruby/blob/trunk/ext/socket/ipsocket.c#L108

SOMAXCONNここでは5と定義されています。

https://github.com/ruby/ruby/blob/trunk/ext/socket/mkconstants.rb#L693

十分な速さでacceptを呼び出さず、キューがいっぱいになった場合はどうなりますか?答えは次のmanページにありますlisten

backlog引数は、sockfdの保留中の接続のキューが大きくなる可能性のある最大長を定義します。キューがいっぱいになったときに接続要求が到着した場合、クライアントはECONNREFUSEDを示すエラーを受け取る可能性があります。または、基になるプロトコルが再送信をサポートしている場合は、要求を無視して、後で接続を再試行できるようにすることができます。

ただし、コードには、5つを超えるクライアントが同時に接続しようとすると、キューがいっぱいになる可能性がある1つの問題があります。それ@thr.joinは、ループの最後で呼び出しているということです。

これを行うと効果的に起こることは、accept-thread内のすべてのものが実行を終了するまで、サーバーは新しい着信接続を受け入れないということです。

そのため、accept-thread内でデータベースやその他の処理に時間がかかる場合、その間にリスニングキューがいっぱいになる可能性があります。これは、処理にかかる時間と、まったく同時に接続している可能性のあるクライアントの数によって異なります。

3
実行しているプラ​​ットフォームはわかりませんが、linux / osxではtop、コンソールで実行するのが最も簡単な方法です。より高度なメモリ監視オプションについては、以下を確認してください。

ruby / ruby​​onRailsメモリリーク検出
トラックアプリケーションのメモリ使用量をherokuで追跡する

于 2012-05-31T00:14:26.403 に答える