繁体   English   中英

Java多线程Web服务器-无法接收多个GET请求

[英]Java Multithreaded Web Server - Not recieving multiple GET requests

我有一个非常基础的多线程Web服务器的启动,它可以接收所有GET请求,只要它们一次出现即可。

但是,当同时收到多个GET请求时,有时会全部收到,而有时却丢失了一些。

我通过创建一个带有多个指向我的网络服务器的图像标签的html页面并在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的评论很明确。 您不应像代码当前那样捕获并忽略异常。 通常,这是一种可怕的做法。 在这种情况下,您很可能会丢掉可以告诉您真正问题是什么的证据。

其次,我认为您可能会误解服务器的功能。 无论您如何实现,服务器每秒只能处理一定数量的请求。 如果您对它提出的请求更多,则必须丢弃一些请求。


我怀疑正在发生的事情是,您在短时间内发送了太多请求,并且淹没了操作系统的请求缓冲区。

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

你能为这个做什么?

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

洞穴

您需要注意一点。 您很有可能可以在短期内修改应用程序以接受(而不是丢弃)更多请求。 但是从长远来看,您应该只接受尽可能快地接受请求的速度。 如果接受它们的速度超过了处理它们的速度,则可能会发生许多不良情况:

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

为了保护自己,实际上最好不要急于接受尽可能多的请求。 相反,请使用有线程池,并调整池大小(等)以优化吞吐率,同时将处理单个请求的时间保持在合理的范围内。

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

  static Socket clientSocket = null;

移除静电后,它现在可以正常使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM