JavamultithreadingWeb服务器 – 未收到多个GET请求

我有一个非常基本的multithreadingWeb服务器的启动,它可以接收所有GET请求,只要它们一次来一个。

但是,当多个GET请求同时进入时,有时它们都会被收到,有时则会丢失一些。

我通过创建一个html页面测试了这一点,该页面包含指向我的web服务器并在firefox中打开页面的多个图像标记。 我总是使用shift + refresh。

这是我的代码,我必须做一些根本错误的事情。

public final class WebServer { public static void main(String argv[]) throws Exception { int port = 6789; ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); } catch(IOException e) { System.err.println("Could not listen on port: " + port); System.exit(1); } while(true) { try { Socket clientSocket = serverSocket.accept(); new Thread(new ServerThread(clientSocket)).start(); } catch(IOException e) { } } } } public class ServerThread implements Runnable { static Socket clientSocket = null; public ServerThread(Socket clientSocket) { this.clientSocket = clientSocket; } public void run() { String headerline = null; DataOutputStream out = null; BufferedReader in = null; int i; try { out = new DataOutputStream(clientSocket.getOutputStream()); in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); while((headerline = in.readLine()).length() != 0) { System.out.println(headerline); } } catch(Exception e) { } } 

首先,@ skaffman的评论是现货。 您不应该像代码当前那样捕获并忽略exception。 一般来说,这是一种可怕的做法。 在这种情况下,你很可能会丢掉可以告诉你真正问题是什么的证据。

其次,我认为你可能会误解服务器的能力。 无论您如何实现它,服务器每秒只能处理一定数量的请求。 如果你向它发出的请求多于此,则必须删除一些请求。


我怀疑发生的事情是你在很短的时间内发送了太多的请求,并且压倒了操作系统的请求缓冲区。

当您的代码绑定到服务器套接字时,操作系统会设置一个请求队列来保存绑定的IP地址/端口上的传入请求。 此队列具有有限的大小,如果在新请求到来时队列已满,操作系统将丢弃请求。 这意味着如果您的应用程序无法足够快地accept请求,则会删除一些请求。

你能为这个做什么?

  • ServerSocket.bind(...)存在重载,允许您指定要在OS级别队列中保留的请求的backlog 。 您可以使用此…或使用更大的待办事项。
  • 您可以更改主循环以更快地从队列中提取请求。 您当前代码的一个问题是您正在为每个请求创建一个新线程。 线程创建很昂贵,您可以通过使用线程池来回收用于先前请求的线程来降低成本。

CAVEATS

你需要小心一点。 很可能您可以修改您的应用程序以在短期内接受(而不是删除)更多请求。 但从长远来看,您应该只接受请求,就像您实际处理它们一样快。 如果它比你处理它们更快地接受它们,可能会发生许多不好的事情:

  • 您将在尝试处理请求的所有线程中使用大量内存。 这将以各种方式增加CPU开销。
  • 您可能会增加内部Java数据结构,数据库等的争用,从而降低吞吐量。
  • 您将增加处理和回复单个GET请求所需的时间。 如果延迟太长,客户端可能会超时请求…并再次发送。 如果发生这种情况,服务器完成的工作将被浪费。

为了防止这种情况,最好不要急切地接受尽可能多的请求。 相反,使用有线程池,并调整池大小(等)以优化吞吐率,同时保持在合理限制内处理单个请求的时间。

我实际上发现问题是这样的:

  static Socket clientSocket = null; 

一旦我移除静电,它现在完美地工作。