一个Web服务器如何在单个端口(80)上同时处理多个传入请求?
例如: 同时有300k用户想要从www.abcdef.com查看一张图片,该网站分配的IP为10.10.100.100和端口80。那么www.abcdef.com如何处理这些传入用户的负载呢?
一个服务器(分配给IP地址10.10.100.100)能否处理如此庞大的传入用户?如果不能,那么如何将一个IP地址分配给多台服务器来处理这个负载呢?
一个Web服务器如何在单个端口(80)上同时处理多个传入请求?
例如: 同时有300k用户想要从www.abcdef.com查看一张图片,该网站分配的IP为10.10.100.100和端口80。那么www.abcdef.com如何处理这些传入用户的负载呢?
一个服务器(分配给IP地址10.10.100.100)能否处理如此庞大的传入用户?如果不能,那么如何将一个IP地址分配给多台服务器来处理这个负载呢?
端口号只是一个神奇的数字,它并不对应硬件设备。服务器打开一个“监听”80端口的套接字,并从该套接字“接受”新连接。每个新连接由一个新的套接字表示,其本地端口也是80端口,但远程IP:端口按连接的客户端而定,因此它们不会混淆。因此,在服务器端不需要多个IP地址甚至多个端口。
使用客户端和服务器套接字标识连接,这为我们在互联网上实现设备之间的多个连接提供了灵活性。例如,繁忙的应用程序服务器进程(如Web服务器)必须能够处理来自多个客户端的连接,否则全球网络将几乎无法使用。由于连接使用客户端套接字以及服务器套接字进行标识,因此这不是问题。同时,Web服务器维护上述连接的同时,可以轻松地与IP地址219.31.0.44上的端口2,199建立另一个连接。这由连接标识符表示:
(41.199.222.3:80, 219.31.0.44:2199).
TCP 负责客户端识别
正如 a.m. 所说,TCP 负责客户端的识别,而服务器只会看到每个客户端的“套接字”。
例如一个位于 10.10.100.100 的服务器在监听端口80上的TCP连接(HTTP是基于TCP协议的)。当一个客户端浏览器(位于 10.9.8.7)使用客户端端口27143 连接到服务器时,服务器会看到:“客户端10.9.8.7:27143想要连接,你接受吗?”。然后服务器会接受,并获得一个“句柄”(即套接字),用来管理与该客户端的所有通信,并且该句柄将始终使用正确的TCP头向10.9.8.7:27143发送数据包。
数据包从不同时到达
实际上,物理上只有一条(或两条)连接将服务器与互联网连接起来,因此数据包只能按顺序到达。这就带来了一个问题:纤维最大吞吐量是多少,服务器可以计算和返回多少响应。除了需要消耗 CPU 时间或在响应请求时存在内存瓶颈外,服务器还必须保持某些资源处于活动状态(至少为每个客户端保持一个活动的套接字)直到通信结束,并因此消耗 RAM。为了实现吞吐量的提高,可以采用一些优化方法(不是互斥的),例如非阻塞套接字(以避免流水线/套接字之间的延迟)、多线程(利用更多的 CPU 核心/线程)。
进一步提高请求吞吐量:负载均衡
最后,网站“前端”的服务器通常不会全部自己完成所有工作(特别是更复杂的任务,如数据库查询、计算等),而会将任务延迟或甚至将 HTTP 请求转发到分布式服务器上,同时继续处理尽可能多的每秒请求(例如转发请求)。将工作分配到几个服务器上被称为负载均衡。
1) 一个Web服务器如何在单个端口(80)上同时处理多个请求?
==> a) Web服务的实例(例如:Spring Boot微服务)在服务器机器上的端口80上运行/监听。
b) 这个Web服务(Spring Boot应用程序)需要一个Servlet容器,如Tomcat。
此容器将配置线程池。
c) 每当来自不同用户的请求同时到达时,此容器将为每个传入的请求分配来自池中的一个线程。
d) 由于服务器端Web服务代码将具有Bean(在Java中的情况下),通常是singleton,因此每个与每个请求相关的线程将调用Singleton API,如果需要访问数据库,则需要这些线程的同步,这是通过@transactional注释完成的。这个注释会同步数据库操作。
2) 一个服务器(分配了IP 10.10.100.100)能够处理这么多的并发用户吗?
如果不能,那么如何将一个IP地址分配给多台服务器以处理此负载?
==> 这将由负载均衡器和路由表来处理。