Я делаю веб-сервер на основе Java. Но когда я тестирую его с ApacheBench, он иногда перестает отвечать.Socket server зависает при тестировании с ab, ожидая BufferedReader.readline()
На Macbook Air:
ab -n 20000 -c 40 -d http://localhost:1080/
гарантированно таймаут после 16400 или больше запросов было сделано.
На Ubuntu столе
ab -n 20000 -c 1000 -d http://localhost:1080/
может успешно сделать большую часть времени, но иногда перестает отвечать на запросы после нескольких прогонов.
Я обнаружил (используя Eclipse), что, когда сервер перестает отвечать на запросы, он ждет BufferedReader.readline(), который я использую для чтения заголовка HTTP-запроса. Но я понятия не имею, почему он ждет.
код Test здесь:
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();
}
}
}
}
}
Кстати, при написании тестового кода, я нашел что-то другое странное
Если
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)»
Но открыт локальный: 1080 с Firefox 4 будет видеть «не читать гнездо» беспорядок показать ,
Вы не закрываете свои сокеты в случае исключения. Вы должны изменить так, чтобы 's.close' был в конечном блоке. (не уверен, что это проблема, но это поможет мне разобраться) –
Не помогая в этом случае, но я думаю, что вы правы. Код обновлен. – CQD