`
lovnet
  • 浏览: 6716386 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

HTTP Keep Alive分析与优化总结

 
阅读更多

一、什么是HTTP Keep Alive


HTTP Keep-Alive 很大程序上被误解了,下面介绍一下它在HTTP/1.0和HTTP/1.1版本下是如何工作的,以及其在JAVA中的运行原理及优化建议。
HTTP是一个请求<->响应模式的典型范例,即客户端向服务器发送一个请求信息,服务器来响应这个信息。在老的HTTP版本中,每个请求都将被创建一个新的客户端->服务器的连接,在这个连接上发送请求,然后接收请求。这样的模式有一个很大的优点就是,它很简单,很容易理解和编程实现;它也有一个很大的缺点就是,它效率很低,因此Keep-Alive被提出用来解决效率低的问题。

具体说,HTTP构建在TCP之上。在HTTP早期实现中,每个HTTP请求都要打开一个socket连接。这种做效率很低,因为一个Web 页面中的很多HTTP请求都指向同一个服务器。例如,很多为Web页面中的图片发起的请求都指向一个通用的图片服务器。持久连接的引入解决了多对已请求服务器导致的socket连接低效性的问题。它使浏览器可以再一个单独的连接上进行多个请求。浏览器和服务器使用Connection头ilai指出对Keep-Alive的支持。

HTTP/1.0


在HTTP/1.0版本中,并没有官方的标准来规定Keep-Alive如何工作,因此实际上它是被附加到HTTP/1.0协议上,如果客户端浏览器支持Keep-Alive,那么就在HTTP请求头中添加一个字段Connection: Keep-Alive,当服务器收到附带有Connection: Keep-Alive的请求时,它也会在响应头中添加一个同样的字段来使用Keep-Alive。这样一来,客户端和服务器之间的HTTP连接就会被保持,不会断开(超过Keep-Alive规定的时间,意外断电等情况除外),当客户端发送另外一个请求时,就使用这条已经建立的连接

HTTP/1.1


在HTTP/1.1版本中,官方规定的Keep-Alive使用标准和在HTTP/1.0版本中有些不同,默认情况下所在HTTP1.1中所有连接都被保持,除非在请求头或响应头中指明要关闭:Connection: Close ,这也就是为什么Connection: Keep-Alive字段再没有意义的原因。另外,还添加了一个新的字段Keep-Alive:,因为这个字段并没有详细描述用来做什么,可忽略它


二、HTTP Keep Alive的注意点


Not reliable(不可靠)


HTTP是一个无状态协议,这意味着每个请求都是独立的,Keep-Alive没能改变这个结果。另外,Keep-Alive也不能保证客户端和服务器之间的连接一定是活跃的,在HTTP1.1版本中也如此。唯一能保证的就是当连接被关闭时你能得到一个通知,所以不应该让程序依赖于Keep-Alive的保持连接特性,否则会有意想不到的后果

Keep-Alive和POST


在HTTP1.1细则中规定了在一个POST消息体后面不能有任何字符,还指出了对于某一个特定的浏览器可能并不遵循这个标准(比如在POST消息体的后面放置一个CRLF符)。而据我所知,大部分浏览器在POST消息体后都会自动跟一个CRLF符再发送,如何解决这个问题呢?根据上面的说明在POST请求头中禁止使用Keep-Alive,或者由服务器自动忽略这个CRLF,大部分服务器都会自动忽略,但是在未经测试之前是不可能知道一个服务器是否会这样做。

三、闲聊Java实现


Java实现--客户端


在客户端,Java抽象了Keep-Alive,和程序员分享离开来,HttpURLConnection类自动实现了Keep-Alive,如果程序员没有介入去操作Keep-Alive,Keep-Alive会通过客户端内部的一个HttpURLConnection类的实例对象来自动实现。也就是说,在java中keep-alive是由一个Java类库来实现的,但在其他类库中不一定可用。

Java实现--服务器端


在服务器端,Java依然是将Keep-Alive抽象出来,HttpServlet、HttpServletRequest、和HttpServletResponse类自动实现 了Keep-Alive。这种情况下一些由第三方控制的操作是可能的,如在KeepAliveServlet中提到的JavaWebServer,Keep-Alive是否启用由两个因素决定,内容长度和输出大小,如果内容长度是响应的一部分(即这段内容长度输出后还有内容需要输出),则Keep-Alive被启用(当然需要客户端支持的情况下);如果内容长度未设定,则Servlet会试着计算响应缓冲区长度以确定内容长度,在Javasoft实现中,使用一个4KB的缓冲区(相当于上面说的响应)。也就是说如果内容长度未设定,并且返回数据超过4KB,此时相当于内容长度大于响应长度,而不是响应长度一部分,Keep-Alive就不会被启用。


四、HTTP Keep Alive 优化例子与总结


4.1 例子分析


问题现象:一个JSP页面,居然要耗时40多秒。网页中有大量的图片的CSS

问题解决:原因也找了半天,原来Apache配置里面,把Keep-Alive的开关关闭了。这个是个大问题,工程师为什么要关闭它,原来他考虑的太简单了,我们知道Apache适合处于短连接的请求,处理时间越短,并发数才能上去,原来他是这么考虑,但是没有办法,只能这样了,还是打开Keep-Alive开关吧。

当然,不是所有的情况都设置KeepAlive为On,下面的文字总结比较好:

【在使用apache的过程中,KeepAlive属性我一直保持为默认值On,其实,该属性设置为On还是Off还是要具体问题具体分析的,在生产环境中的影响还是蛮大的。

KeepAlive选项到底有什么用处?如果你用过Mysql,应该知道Mysql的连接属性中有一个与KeepAlive类似的Persistent Connection,即:长连接(PConnect)。该属性打开的话,可以使一次TCP连接为同一用户的多次请求服务,提高了响应速度。

比如很多网页中图片、CSS、JS、Html都在一台Server上,当用户访问其中的Html网页时,网页中的图片、Css、Js都构成了访问请求,打开KeepAlive属性可以有效地降低TCP握手的次数(当然浏览器对同一域下同时请求的图片数有限制,一般是2 见下文章节少域名解释的开销),减少httpd进程数,从而降低内存的使用(假定prefork模式)。MaxKeepAliveRequestsKeepAliveTimeOut两个属性在KeepAlive=On时起作用,可以控制持久连接的生存时间和最大服务请求数。


不过,上面说的只是一种情形,那就是静态网页居多的情况下,并且网页中的其他请求与网页在同一台Server上。当你的应用动态程序(比如:php)居多,用户访问时由动态程序即时生成html内容,html内容中图片素材和Css、Js等比较少或者散列在其他Server上时,KeepAlive=On反而会降低Apache的性能。为什么呢?

前面提到过,KeepAlive=On时,每次用户访问,打开一个TCP连接,Apache都会保持该连接一段时间,以便该连接能连续为同一client服务,在KeepAliveTimeOut还没到期并且MaxKeepAliveRequests还没到阈值之前,Apache必然要有一个httpd进程来维持该连接,httpd进程不是廉价的,他要消耗内存和CPU时间片的。假如当前Apache每秒响应100个用户访问,KeepAliveTimeOut=5,此时httpd进程数就是100*5=500个(prefork模式),一个httpd进程消耗5M内存的话,就是500*5M=2500M=2.5G,夸张吧?当然,Apache与Client只进行了100次TCP连接。如果你的内存够大,系统负载不会太高,如果你的内存小于2.5G,就会用到Swap,频繁的Swap切换会加重CPU的Load。

现在我们关掉KeepAliveApache仍然每秒响应100个用户访问,因为我们将图片、js、css等分离出去了,每次访问只有1个request,此时httpd的进程数是100*1=100个,使用内存100*5M=500M,此时Apache与Client也是进行了100次TCP连接。性能却提升了太多。

4.2 总结


1、当你的Server内存充足时,KeepAlive=On还是Off对系统性能影响不大。

2、当你的Server上静态网页(Html、图片、Css、Js)居多时,建议打开KeepAlive

3、当你的Server多为动态请求(因为连接数据库,对文件系统访问较多),KeepAlive关掉,会节省一定的内存,节省的内存正好可以作为文件系统的Cache(vmstat命令中cache一列),降低I/O压力。

PS:当KeepAlive=On时,KeepAliveTimeOut的设置其实也是一个问题,设置的过短,会导致Apache频繁建立连接,给Cpu造成压力,设置的过长,系统中就会堆积无用的Http连接,消耗掉大量内存,具体设置多少,可以进行不断的调节,因你的网站浏览和服务器配置而异。


4.3 减少域名解释的开销


对于HTTP/1.0来说可以充分利用浏览器默认最大并发连接数比HTTP/1.1多的好 处,实现不增加新域名的开销而更高的并行下载,减少域名解释的开销(注:IE 6,7在HTTP/1.0中默认最大并发连接数为4,在HTTP/1.1中默认最大并发连接数为2,IE8都为6,Firefox2在HTTP/1.0中 默认最大并发连接数为2 在HTTP/1.1中默认最大并发连接数为8,firefox 3默认都是6),根据10年7月Google索引的42亿个网页的统计报告,每张网页里包含29.39个图片,7.09个外部脚本,3.22个外部CSS 样式表,如果设置了Keep-Alive并且合理控制Keep-Alive TimeOut这个参数可以大量的节约连接的开销,提高相应速度。如果设置不好,在大并发的情况小,因维持大量连接而使服务器资源耗尽,而对于目前国内大 部分的用户使用的还是IE6,7的情况下关闭Keep-Alive可以充分利用浏览器默认最大并发连接数的好处实现不增加额外的开销页面快速的展示。

分享到:
评论

相关推荐

    vue中keep-alive,include的缓存问题

    主要介绍了vue中keep-alive,include的缓存问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    Vue中对iframe实现keep alive无刷新的方法

    一开始使用了Vue自带的keep- alive发现没有用,于是自己研究了一下解决方案。。。。。。 Vue的keep-alive原理 要实现对保持iframe页的状态。我们先搞清楚为什么Vue的keep-alive不能凑效。keep-alive原理是把组件里...

    HTTP协议Keep-Alive模式详解

    HTTP协议Keep-Alive模式详解

    利用Keep-Alive处理Socket网络异常断开的方法

    今天讲一下网络方面的知识,希望对你的学习提供很好的帮助。

    HTTP协议Keep-Alive模式详解和HTTP头字段总结

    主要介绍了HTTP协议Keep-Alive模式详解和HTTP头字段总结,需要的朋友可以参考下

    keep-alive的介绍及使用

    如果需要频繁切换路由,这个时候就可以考虑用keep-alive了,来达到避免数据的重复请求的目的 keep-alive用来缓存组件,避免多次加载相应的组件,减少性能消耗。 简单一点来说就是从页面A链接到其他页面后回退到页面A...

    vue2中的keep-alive使用总结及注意事项

    vue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗。本文给大家介绍vue2中的keep-alive使用总结及注意事项,需要的朋友参考下吧

    react-keep-alive:保持组件状态并避免重复渲染的组件

    React保持活力 保持组件状态并避免重复渲染的组件。 English | :sparkles: 特征不基于React Router,... 要将React Keep Alive与React应用程序一起使用: npm install --save react-keep-alive :hammer: 用法React Kee

    彻底揭秘keep-alive原理(小结)

    二、keep-alive介绍与应用 2.1 keep-alive是什么 keep-alive是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。 2.2...

    vue中keep-alive的用法及问题描述

    1.keep-alive的作用以及好处 在做电商有关的项目中,当我们第一次进入列表页需要请求一下数据,当我从列表页进入详情页,详情页不缓存也需要请求下数据,然后返回列表页,这时候我们使用keep-alive来缓存组件,防止...

    vue组件 keep-alive 和 transition 使用详解

    1.keep-alive 能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 相似, 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件...

    keep-alive.7z

    keep-alive 案例

    vue中keep-alive内置组件缓存的实例代码

    将要缓存的组件使用 keep-alive 包裹住即可。 keep-alive优点的介绍: 1. 切换组件时,当前组件不会触发销毁的生命周期钩子。也就是说不会销毁了。 2. 切换回来时,也不会重新创建。(既然都没有被销毁,哪里来的...

    深入理解Vue keep-alive及实践总结

    什么是 keep-alive 在平常开发中,有部分组件没有必要多次初始化,这时,我们需要将组件进行持久化,使组件的状态维持不变,在下一次展示时,也不会进行重新初始化组件。 也就是说,keepalive 是 Vue 内置的一个...

    vue使用keep-alive切换页面,2种方法实现页面保持滚动位置.zip

    vue使用keep-alive切换页面,2种方法实现页面保持滚动位置 下载后 先 npm i 安装依赖

    keep-alive保持组件状态的方法

    keep-alive的设计初衷 有些业务场景需要根据不同的判断条件,动态地在多个组件之间切换。频繁的组件切换会导致组件反复渲染,如果组件包含有大量的逻辑和dom节点,极易造成性能问题。其次,切换后组件的状态也会完全...

    vue keep-alive 动态删除组件缓存的例子

    3、当前组件的route-view,外层包裹keep-alive,include用你从仓库里面取出来的数组 4、关闭标签页(也就是后退路由的时候),清空store里的数组 总结:通过动态的设置include(要缓存的组件)的数组,来动态的控制...

    keep-alive不能缓存多层级路由菜单问题解决

    目前keep-alive可以有效缓存一级,二级的路由菜单,3级以上菜单并不能做到缓存,这里提供一个解决方案: 在cachedViews中手动加上一级菜单和三级菜单之间,缺失的二级菜单的名字,这样二级菜单下的组件就会缓存了 ...

    umi-plugin-keep-alive:用于基于React激活的umijs

    umi-plugin-keep-alive 中文说明 | 此 &lt;KeepAlive&gt; 功能基于 在线示例 umi 多 tabs 示例: 使用方法 安装 npm install umi-plugin-keep-alive --save # or yarn add umi-plugin-keep-alive 从 umi 中导出 KeepAlive...

Global site tag (gtag.js) - Google Analytics