2011-04-08 9 views
0

JavaベースのWebサーバーを作成しています。しかし、私がApacheBenchでテストしているときに、応答が止まることがあります。 Macbook Airはオンabでテストしたときにソケットサーバーがハングしました。BufferedReader.readline()

ab -n 20000 -c 40 -d http://localhost:1080/ 

は16400の以上の要求が行われた後にタイムアウトすることが保証されます。 Ubuntuのデスクトップで

ab -n 20000 -c 1000 -d http://localhost:1080/ 

が正常にほとんどの時間をし、時にはいくつかの実行後に応答を停止可能性があります。

私は、サーバーが応答を停止したときに、HTTP要求ヘッダーの読み取りに使用するBufferedReader.readline()を待機していることを確認しました。しかし、私はなぜそれが待っているのか分かりません。

テストコードここにある:

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 
String line = br.readLine(); 

String line = "don't read the socket"; 
に置き換えている場合は

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class TestServer { 
    public static void main(String[] args){ 
     ServerSocket socket = null; 

     try{ 
      socket = new ServerSocket(1080); 
      ExecutorService pool = Executors.newFixedThreadPool(10); 
      while(true){ 
       Socket s = socket.accept(); 
       pool.execute(new RequestHandler(s)); 
      } 
     } 
     catch(Exception e){ 
      e.printStackTrace(); 
     } 
     finally{ 
      if(null!=socket){ 
       try { 
        socket.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

    } 
} 

class RequestHandler implements Runnable{ 
    final Socket s; 
    public RequestHandler(Socket s) { 
     this.s = s; 
    } 

    public void run() { 
     try { 
      BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 
      String line = br.readLine(); 

      PrintWriter pw = new PrintWriter(s.getOutputStream()); 
      pw.print("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); 
      pw.print(line); 
      pw.flush(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     finally{ 
      if(s!=null){ 
       try { 
        s.close(); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

はところで、テストコードを書くとき、私は他の何か奇妙な

を見つけました

abこのようなメッセージで失敗します:「apr_socket_recv:接続が拒否(111)ピアによってリセット接続(104)」

しかし、オープンはlocalhost:Firefoxの4との1080年には「ソケットを読んでいない」混乱は表示が表示されます。

+1

例外が発生した場合でもソケットを閉じるわけではありません。 's.close'がfinallyブロックに入るように変更する必要があります。 (それが問題なのかどうかは分かりませんが、それは明確なことを助けるでしょう) –

+0

このケースでは役に立たないが、私はあなたが正しいと思う。コードが更新されました。 – CQD

答えて

1

これはApacheBenchテストの意図的な部分であるかどうか疑問です。つまり、サーバーが接続を開いたときにサーバーがどのように動作するのかを確認しても、データは送信されません。おそらくApacheBenchはオープンソースなので、16400の試行後に何か特別な動作(私の賭けはソケットを開き、要求を送信しないでください)を呼び出すかどうかを見ることができます。

いずれの場合でも、Javaのバージョンがデフォルトで0(=無限)になっている場合に、ソケットに明示的なタイムアウトを設定することをお勧めします。すべてのクライアントが完全に動作し、常に期待しているデータを正確に送信すると想定しないでください。

一般的なルールとして、「何か異常なことが起きた」場合、Webサーバーが倒れないようにする必要があります。ネットワークはそのようなもので、パケット/接続がランダムに破棄されることがあります。それに対処する。オペレーティングシステムは、例えば、どのくらいの時間接続を開くことができるので、あなたのサーバーは突然OSの「足元から引っ張られた敷物」を見ることができます。私はApacheBenchテストがこのようないくつかのグレムリンをシミュレートしていると思います(私が言及しているように、readLine()はおそらく開いている接続でリクエストを送信しないシミュレーションですが)Ubuntuで見ることもできます。

関連する問題