关于HTTP中的keep-alive

一. 关于HTTP

首先,HTTP是超文本传输协议,是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,其主要特点有如下:

  1. 支持客户/服务器模式;
  2. 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快;
  3. 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记;
  4. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间;
  5. 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快

二. keep-alive

既然上面提到了HTTP是基于请求与响应的,且最主要的两个特点就是无连接和无状态,但需要说明的是,虽然是无连接的,但其底层也就是传输层大多却是基于
TCP面向连接的通信方式,因此,这里的无连接指的是:当server端和client端进行通讯的时候,client端向server端发起请
求,server端接收请求之后返回给client端一个响应,之后就会断开不再继续保持连接了;这样有一个好处就是对于只有一次访问的连接来说不仅节省
资源还很高效,但很明显,如果client端还想继续多次访问server端就需要重新建立连接也就是会多次进行TCP的“三次握手,四次挥手”的过程,
这样一来并没有节省资源而且还很低效,因此,使用keep-alive(又称持久连接、连接重用)可以改善这种状态,即在一次TCP连接中可以持续发送多份数据而不会断开连接。通过使用keep-alive机制,避免了建立或者重新建立连接的次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能和提高httpd服务器的吞吐率(更少的TCP连接意味着更少的系统内核调用,socket的accept()和close()调用)。


HTTP 1.0
中keep-alive默认是关闭的,需要在HTTP头加入"Connection: Keep-Alive",才能启用Keep-Alive;HTTP
1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。目前大部分浏览器都是用HTTP
1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。

其中,RFC 2616 (P47)指出:单用户客户端与任何服务器或代理之间的连接数不应该超过2个。一个代理与其它服务器或代码之间应该使用不超过2 * N的活跃并发连接。这是为了提高HTTP响应时间,避免拥塞(冗余的连接并不能代码执行性能的提升)。

三. keep-alive timeout时间

keep-alive并不是免费的午餐,长时间的TCP连接容易导致系统资源无效占用,配置不当的keep-alive 有时比重复利用连接带来的损失还更大;因此,正确地设置keep-alive timeout时间非常重要。

httpd守护进程一般都提供了keep-alive
timeout时间设置参数,比如nginx的keepalive_timeout和Apache的keepalivetimeout。这个
keepalive_timeout时间值意味着:一个http产生的TCP连接在传送完最后一个响应后,还需要保持keepalive_timeout
时间后才开始关闭这个连接;

在没有设置keepalive_timeout的情况下,一个socket资源从建立到真正释放所需要经过的时间是:建立TCP连接(三次握手)+传送http请求+脚本指向+传送http响应+关闭TCP连接(四次挥手)+主动关闭的一方进入TIME_WAIT的2MSL等待时间;

    当设定了keepalive_timeout时间之后,一个socket由建立到释放所需要经过的时间是:TCP建立连接(三次握手)+(最后一次响应 - 第一次请求时间)+TCP关闭连接(四次挥手)+2MSL;
也就是说,当使用keep-alive机制的时候,当一次请求-响应结束之后,这个连接还会继续维持上keepalive_timeout时间,如果在这
个时间内client端还有请求发过来,那么server端会继续处理给予响应,如果keepalive_timeout时间计时结束后,就会进入TCP
释放连接的阶段,因此也就会结束掉这次通信;

四. keep-alive模式的使用

虽然keep-alive模式可以降低TCP连接的次数提高效率,但并不是什么情况下都适合使用keep-alive机制的,如下举个栗子:

比如很多网页中图片、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连接。性能却提升了太多。

因此,总结:

  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连接,消耗掉大量内存,具体设置多少,可以进行不断的调节,因你的网站浏览和服务器配置而异。

时间: 2024-10-12 09:09:14

关于HTTP中的keep-alive的相关文章

Linux下关于TCP的keep alive的实现源码分析

TCP下的Keep Alive 我们常说的TCP的keep alive,就是为了保证连接的有效性,在间隔一定的时间发探测包,根据回复来确认该连接是否有效.通常上层应用会自己提供心跳检测机制,而Linux内核本身也提供了从内核层面的确保连接有效性的方式. 在sock 函数中可以设置是否需要打开keep alive开关,默认建立socket 是关闭keep alive的.代码如下 optval = 1; optlen = sizeof(optval); if(setsockopt(s, SOL_SO

Spark schedule资源调度分配详解

一:任务调度与资源调度的区别 1. 任务调度:是通过DAGScheduler,TaskScheduler,SchedulerBackend等进行的作业调度: 2. 资源调度:是指应用程序如何获得资源: 3. 任务调度时在资源调度的基础上进行的,没有资源调度那么任务调度就成为了无源之水,无本之木. 二:资源调度内幕天机揭秘 1. 因为Master负责资源管理和调度,所以资源调度的方法schedule位于Master.scala这个类中,当注册程序或者资源发生改变的时候都会导致schedule的调用

并发编程之线程与锁

线程是操作系统调度的最小单位,随着多核处理器的流行多线程编程成为能有效发挥cpu潜能的利器(python除外).线程之间的内存是共享,所以创建一个线程所需要的开销比创建一个进程的开销要小得多.抛开硬件层面,多线程也给我们提供同时执行多个任务的手段(并发编程),使得我们能有另一种编程思维.python的线程都封装在threading模块中. threading threading.active_count(): 返回当前活跃的线程数,返回数等于由模块中另一个方法 enumerate()返回的列表的

第31课:Spark资源调度分配内幕天机彻底解密:Driver在Cluster模式下的启动、两种不同的资源调度方式源码彻底解析、资源调度内幕总结

本課主題 Master 资源调度的源码鉴赏 Spark 的 Worker 是基于什么逻辑去启动 Executor 资源调度管理 任務調度與資源是通過 DAGScheduler.TaskScheduler.SchedulerBackend 等進行的作業調度 資源調度是指應用程序如何獲得資源 任務調度是在資源調度的基礎上進行的,沒有資源調度那麼任務調度就成為了無源之水無本之木 Master 资源调度的源码鉴赏 因為 Master 負責資源管理和調度,所以資源調度方法 scheduer 位於 Mast

HAProxy出现"远程主机强迫关闭了一个现有的连接 " 的错误及解决

使用haproxy作为sql server 的负载均衡器. 使用了文档中的示例配置项: timeout client 50s        timeout server 50s 采用这个配置项,有时会出现“远程主机强迫关闭了一个现有的连接”的错误. 出现这个错误的原因是:一旦sql client超过50s没有给haproxy发送数据,则haproxy会关闭这个连接,此时sql client中的以为连接还是通的,此时发送数据就会出现异常. 在查看了HAProxy的官方文档,以及mysql和sql

Lucene的分析资料【转】

Lucene 源码剖析 1 目录 2 Lucene是什么 2.1.1 强大特性 2.1.2 API组成- 2.1.3 Hello World! 2.1.4 Lucene roadmap 3 索引文件结构 3.1 索引数据术语和约定 - 3.1.1 术语定义 3.1.2 倒排索引(inverted indexing) 3.1.3 Fields的种类 3.1.4 片断(segments) 3.1.5 文档编号(document numbers) 3.1.6 索引结构概述 3.1.7 索引文件中定义的

如何在socket编程的Tcp连接中实现心跳协议

心跳包的发送,通常有两种技术 方法1:应用层自己实现的心跳包 由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:服务器在一个 Timer事件中定时 向客户端发送一个短小精悍的数据包,然后启动一个低级别的线程,在该线程中不断检测客户端的回应, 如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线:同样,如果客户端在一定时间内没 有收到服务器的心跳包,则认为连接不可用. 方法2:TCP的KeepAlive保活机制 因为要考虑到一个服务器通常会连接多个客户端,因此由用户在应用层自己实现心

TCP中的长连接和短连接(转载)

原文地址:http://www.cnblogs.com/onlysun/p/4520553.html 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需要4次挥手,所以说每个连接的建立都是需要资源消耗和时间消耗的 示意图: 长连接: 所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以

[转]JVM系列四:生产环境参数实例及分析【生产环境实例增加中】

原文地址:http://www.cnblogs.com/redcreen/archive/2011/05/05/2038331.html java application项目(非web项目) 改进前: -Xms128m-Xmx128m-XX:NewSize=64m-XX:PermSize=64m-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=78-XX:ThreadStackSize=128-Xloggc:logs/gc.log

emacs 中的键盘宏

PING(Packet InterNet Groper)中文名为因特网包探索器,是用来查看网络上另一个主机系统的网络连接是否正常的一个工具.ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把回复报文传回给发送者,这有点象潜水艇声纳系统中使用的发声装置.所以,我们想知道我这台主机能不能和另一台进行通信,我们首先需要确认的是我们两台主机间的网络是不是通的,也就是我说的话能不能传到你那里,这是双方进行通信的前提.在Linux下使用指令ping的方法和现象