当只有一个进程可以侦听和接受给定的 IP 地址和端口组合时,Web 服务器如何扩展以侦听数百万个传入请求?这个问题与找出用于缩放的套接字编程的大纲有关,因此我不是在寻找使用硬件缩放解决方案的负载平衡,我也不是在寻找 Web 套接字实现,而是在寻找基本的低级套接字编程。
如果我必须编写一个 Web 服务器来监听传入的 http 请求,那么监听传入请求的线程的设计大纲应该是什么,以便它扩展到数百万个传入请求?
当只有一个进程可以侦听和接受给定的 IP 地址和端口组合时,Web 服务器如何扩展以侦听数百万个传入请求?这个问题与找出用于缩放的套接字编程的大纲有关,因此我不是在寻找使用硬件缩放解决方案的负载平衡,我也不是在寻找 Web 套接字实现,而是在寻找基本的低级套接字编程。
如果我必须编写一个 Web 服务器来监听传入的 http 请求,那么监听传入请求的线程的设计大纲应该是什么,以便它扩展到数百万个传入请求?
我为自己写了一个小聊天服务器(基本上做同样的事情)。
我采用的设计是第一个接受连接的线程(基本上是一个循环,在对象实例上while
迭代)。该线程是 连接。accept()
ServerSocket
listening to
对于由返回的每个连接accept()
,我启动了一个单独的线程来处理reads from
该连接。所有这些线程引用都存储在同步中List
以供进一步处理,例如稍后关闭连接等等。
如果您想要数百万个并发连接,那么您将无法实现。限额通常为数千。另一方面,如果您希望每秒处理数百万个请求,那么您也许可以摆脱它,但前提是您的请求处理是最简单的类型并且响应非常短。
通常,如果您在 Java 中执行此操作,则不应使用标准阻塞java.io
API,因为每个连接都会占用两个线程:一个用于读取,一个用于写入。而是使用允许异步 TCP 通信的 Netty 库,这意味着只有中等大小的线程池才能处理大量请求:线程永远不会空闲等待接收输入或发送输出。他们只忙于处理数据。
你把“听”和“读”混为一谈。他们不是一回事。“侦听”意味着服务器创建一个侦听套接字,可以从中接受大量连接。然后读取和写入这些连接中的每一个。