2011-04-08 4 views
0

Java 기반 웹 서버를 만들고 있습니다. 그러나 ApacheBench로 테스트 할 때 때때로 응답을 멈 춥니 다. 맥북 에어에 ab로 테스트 할 때 소켓 서버가 멈추었습니다. BufferedReader.readline()

:

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

는 16,400 이상의 요청이 완료 된 후에 시간 초과 보장됩니다. 우분투 데스크탑

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

성공적으로 대부분의 시간을 완료,하지만 때로는 여러 실행 후 응답을 중지 할 수 있습니다.

이클립스를 사용하여 서버가 응답을 멈췄을 때 HTTP 요청 헤더를 읽는 데 사용하는 BufferedReader.readline()을 기다리고 있음을 확인했습니다. 그러나 나는 왜 그것이 기다리고 있는지 전혀 모른다.

테스트 코드는 여기에 있습니다 :

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(); 
       } 
      } 
     } 
    } 
} 

BTW 테스트 코드를 작성할 때, 나는

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

String line = "don't read the socket"; 
로 대체

경우 다른 이상한 것을 발견

ab "apr_socket_recv : 연결이 거부되었습니다 (111) 피어 (104)에 의한 연결 재설정"

Firefox 4에서 localhost : 1080을 열면 "소켓을 읽지 마십시오"라는 메시지가 나타납니다. .

+1

예외가 발생할 경우 소켓을 닫지 않습니다. 's.close'가 finally 블록에 있도록 변경해야합니다. (문제인지 여부는 확실하지 않지만 명확한 정보를 얻는 데 도움이됩니다.) –

+0

이 경우 도움이되지 않지만 나는 당신이 옳다고 생각합니다. 코드가 업데이트되었습니다. – CQD

답변

1

이것이 ApacheBench 테스트의 고의적 인 부분인지 궁금합니다. 연결을 열었을 때 서버가 어떻게 작동하는지보고 싶지만 데이터는 전송되지 않습니다. 아마도 ApacheBench는 오픈 소스이기 때문에 16400 번 시도 후에 특별한 동작 (소켓을 열고 나서 요청을 보내지 않음)을 호출하는지 확인할 수 있습니다.

어쨌든 Java 버전이 기본값 0 (= 무한대) 인 경우 소켓에 명시적인 시간 초과를 설정해야합니다. 모든 고객이 완벽하게 행동하고 예상 한 데이터를 항상 정확하게 전달할 것이라고 가정하지 마십시오.

일반적으로 "이상한 일이 발생하면"웹 서버가 넘어지지 않도록해야합니다. 예를 들어 네트워크가 그렇듯이 패킷/연결이 무작위로 삭제 될 수도 있습니다. 받아 들여. 운영 체제는 예를 들어, 연결이 열려있을 수있는 시간과 OS가 서버에 갑자기 "발 밑에 깔아 놓은 깔개"를 볼 수 있습니다. ApacheBench 테스트가 우분투에서 볼 수있는 몇 가지 gremlins를 시뮬레이트 할 수 있다고 상상해 봅니다. 비록 readLine() 함수가 열린 커넥션에 대한 요청을 보내지 않는 시뮬레이션 일 것입니다.

관련 문제