http保持在现代

所以根据haproxy作者,谁知道关于http:

发明了“保持活力”,以便在CPU速度降低100倍时降低服务器上的CPU使用率。 但是没有说的是,持久连接会消耗大量的内存,除了打开它们的客户端之外,任何人都不能使用它们。 今天在2009年,CPU的价格非常便宜,内存仍然限制在几千兆的架构或价格。 如果一个网站需要保持活力,那么确实存在一个问题。 高负载的网站通常禁用保持活动,以支持最大数量的同时客户端。 没有保持活力的真正缺点是获取对象的延迟稍微增加。 浏览器将非保持活动网站上的并发连接数加倍,以弥补这一点。

(来自http://haproxy.1wt.eu/ )

这是否符合其他民族的经验? 即没有保持活力 – 是现在几乎不可知的结果? (它可能值得注意的是,使用websockets等 – 连接保持“打开”无论如何保持活着状态 – 对于响应速度非常快的应用程序)。 对于远离服务器的人来说效果会更好 – 或者在加载页面时从同一主机加载的工件数量很多? (我认为像CSS,图像和JS越来越多来自caching友好的CDN)。

思考?

(不知道这是否是一个serverfault.com的事情,但我不会交,直到有人告诉我把它移到那里)。

嘿,因为我是这个引文的作者,我会回应:-)

在大型网站上有两个大问题:并发连接和延迟。 并发连接是由需要长时间下载内容的慢速客户端以及空闲连接状态引起的。 这些空闲的连接状态是由连接重用引起的,以获取多个对象,称为保持活动(Keep-alive),这会进一步增加等待时间。 当客户端与服务器非常接近时,可以大量使用连接并确保它几乎不会闲置。 然而,当序列结束时,没有人关心快速closures频道,并且连接长时间保持打开和未使用状态。 这就是为什么很多人build议使用非常低的保活超时。 在一些像Apache这样的服务器上,可以设置的最低超时时间为1秒,而且维持高负载往往是太多了:如果在您面前有20000个客户端,并且每秒平均获取一个对象,有永久build立20000个连接。 在像Apache这样的通用服务器上,20000个并发连接是非常庞大的,根据加载的模块的不同,需要32到64 GB的内存,而且即使增加了内存,你也不希望高得多。 实际上,对于20000个客户端,你甚至可能会在服务器上看到40000到60000个并发连接,因为如果浏览器有很多对象要获取,它们将尝试build立2到3个连接。

如果在每个对象之后closures连接,并发连接的数量将急剧下降。 实际上,它会下降一个对应于下载对象的平均时间的因素。 如果你需要50毫秒来下载一个对象(一个微缩照片,一个button等),并且你每秒平均下载一个对象,那么你将只有每个客户端有0.05个连接,这只有1000个20000个客户端的并发连接。

现在,build立新连接的时间将被计算在内。 远程客户端会遇到不愉快的延迟。 过去,浏览器在保持活动状态时被用来使用大量的并发连接。 我记得MSIE上的4位数字和Netscape上的8位数字。 这实际上将平均每个对象的延迟分成了这么多。 现在无处不在,现在我们看不到这么高的数字了,因为这样做会进一步增加远程服务器的负载,而浏览器负责保护互联网的基础设施。

这意味着,在今天的浏览器中,使非保持活动服务与保持活动的服务一样响应更为困难。 另外,一些浏览器(例如:Opera)使用启发式来尝试使用pipelinining。 stream水线是使用保持活动的有效方式,因为它通过发送多个请求而不用等待响应几乎消除了延迟。 我已经在一个有100张小照片的页面上尝试过了,第一次访问的速度是没有保存时​​的两倍,但是下一次访问的速度是快8倍,因为响应非常小,只有延迟计数“304”响应)。

我想说,理想情况下,我们应该在浏览器中使用一些可调参数,以使它们保持连接在所获取的对象之间,并在页面完成时立即删除它们。 但是我们不幸看到这一点。

出于这个原因,一些需要在前端安装通用服务器(如Apache)并且必须支持大量客户端的站点通常必须禁用保持活动状态。 为了强制浏览器增加连接数量,他们使用多个域名,以便下载可以并行化。 在密集使用SSL的网站上,问题尤其严重,因为连接设置更高,因为还有一次往返。

现在更常见的是,这样的网站更喜欢安装haproxy或nginx之类的轻量级前端,它们在处理数十到数十万个并发连接时没有问题,它们使客户端保持活动状态,并在Apache方面。 在这方面,build立连接的成本在CPU方面几乎是空的,而且根本不明显。 这样就提供了两全其美的优势:由于保持活跃,客户端的超时时间很短,服务器端的连接数量较less,所以延迟时间较短。 大家都开心 :-)

一些商业产品通过重新使用前端负载均衡器和服务器之间的连接并通过它们复用所有客户端连接来进一步改善这一点。 当服务器靠近LB时,增益并不比以前的解决scheme高很多,但是经常需要对应用进行调整,以确保不会因为多个用户之间意外的共享连接而造成用户之间会话通过的风险。 理论上这绝不应该发生。 现实是非常不同的:-)

在写这些(并在这里发布stackoverflow)这些年来,我们现在有服务器,如nginx,这是越来越stream行。

例如,nginx可以在一个进程中只保留2.5 MB(兆字节)的内存,保持10,000次保持连接。 实际上,使用非常less的RAM容易地保持连接数千个连接,并且唯一的限制是其他限制,例如打开文件句柄或TCP连接的数量。

保持活力是一个问题,不是因为keep-alive规范本身存在任何问题,而是因为Apache基于进程的缩放模型以及被保护的攻击者侵入了一个服务器,而这个服务器的体系结构并不适合它。

特别有问题的是Apache Prefork + mod_php + keep-alives。 这是一种模式,即每个连接都将继续占用PHP进程占用的所有内存,即使它完全处于空闲状态,只能保持为保持活动状态。 这是不可扩展的。 但是服务器不必这样devise – 服务器不需要在一个单独的进程中保持每个保持连接的连接(特别是当每个这样的进程都有一个完整的PHP解释器时)。 PHP-FPM和一个基于事件的服务器处理模型(例如nginx中的)可以很好地解决这个问题。

2015年更新:

SPDY和HTTP / 2用更好的东西取代了HTTP的keep-alivefunction:不仅能够保持连接的活动并对其进行多重请求和响应,而且对它们进行复用,所以响应可以以任何顺序发送,而不是只按照要求的顺序。 这可以防止缓慢的响应阻止更快的响应,并消除了浏览器保持打开多个并行连接到单个服务器的诱惑。 这些技术进一步突出了mod_php方法的不足之处,以及诸如基于事件(或者至less是multithreading)的web服务器与PHP-FPM之类的东西分开连接的好处。

我的理解是,它与CPU没有多大关系,而是在向世界另一端开放重复套接字的延迟。 即使你有无限的带宽,连接延迟也会减慢整个过程。 放大,如果你的网页有几十个对象。 即使一个持续的连接有一个请求/响应延迟,但是当你有2个套接字平均时,这个延迟就减less了,一个应该是stream数据而另一个可能被阻塞。 此外,路由器永远不会假设一个套接字连接之前让你写信给它。 它需要完整的往返握手。 再次,我不认为是专家,但这是我总是看到它。 真的很酷的是一个完全ASYNC协议(不,不是一个完全不舒服的协议)。

如果您使用CloudFront或CloudFlare等“原始拉取”CDN,非常长的保活可能很有用。 事实上,即使您提供完全dynamic的内容,这也可以比没有CDN更快。

如果你长期保持活力,每个PoP基本上与你的服务器有永久连接,那么当用户第一次访问你的站点时,他们可以用本地PoP做一个快速的TCP握手,而不是和你握手。 (光本身需要100毫秒的时间才能通过光纤到达全世界,build立TCP连接需要三个数据包来回传递, SSL需要三次往返) 。