使客户端到服务器端的链接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了创建或者从新创建链接。
HTTP/1.0中默认使用Connection:close, 在HTTP/1.1中已经默认使用Connection: keep-alive。TCP协议层默认并不开启KeepAlive功能。
java
http1.1中因默认支持长链接,因此若是不但愿使用则须要在header中指明connection的值为close;而server也不想支持,则在response中也须要明确说明connection的值为close。
HTTP Connection的 close设置容许客户端或服务器中任何一方关闭底层的链接时双方都会要求在处理请求后关闭它们的TCP链接。即不管request仍是response的header中包含了值为close的connection,都代表当前正在使用的tcp连接在请求处理完毕后会被断掉,之后client再进行新的请求时就必须建立新的tcp连接了。(程序中能够在过滤器中加入:response.setHeader("connection", "close");)
浏览器在请求头部添加 Connection:keep-alive,以此告知服务器本身支持长链接方式,而假若服务器也支持,那么就在响应头部添加 Connection:keep-alive,从而告诉浏览器长链接。服务器还能够经过 Keep-Alive:timeout=10, max=100 的头部告诉浏览器“10 秒算超时时间,最长不能超过 100 秒”。 客户端和服务端均可以设置timeout和max属性值,但http链接保持时间是由服务端的消息头connection字段和keep-alive字段定的!linux
//org.apache.http.impl.execchain.MainClientExec#execute ...... //从链接池中lease connection final HttpClientConnectionmanagedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS); ...... //将conenction封装在ConnectionHolder中 final ConnectionHolder connHolder = new ConnectionHolder(this.log, this.connManager, managedConn); ...... // The connection is in or can be brought to a re-usable state. //若是返回值消息头中connection设置为close,则返回false if (reuseStrategy.keepAlive(response, context)) { // Set the idle duration of this connection //取出response消息头中,keep-alive的timeout值 final long duration = keepAliveStrategy.getKeepAliveDuration(response, context); if (this.log.isDebugEnabled()) { final String s; if (duration > 0) { s = "for " + duration + " " + TimeUnit.MILLISECONDS; } else { s = "indefinitely"; } this.log.debug("Connection can be kept alive " + s); } //设置失效时间 connHolder.setValidFor(duration, TimeUnit.MILLISECONDS); connHolder.markReusable(); } else { connHolder.markNonReusable(); }
http keep-alive 意图在于链接复用。是为了让TCP存活更久以便复用TCP链接,在一个TCP链接上进行屡次的HTTP请求从而提升性能。
tcp KeepAlive是TCP的一种检测TCP链接情况的保鲜机制, 意图在于保活、心跳,检测链接错误。
TCP通常而言为服务器端提供保活功能: 若是客户端已经消失,使得服务器上保留一个半开放的链接,而服务器又在等待来自客户端的数据,则服务器将永远等待客户端的数据, 保活功能就是试图在服务器端检测到这种半开放的链接。nginx
及时有效地检测到一方的非正常断开,保证链接的资源被有效利用。apache
Tomcat中的相关设置,在conf/server.xml 中的Connector 元素中: keepAliveTimeout: The number of milliseconds this Connector will wait for another HTTP request before closing the connection. The default value is to use the value that has been set for the connectionTimeout attribute. maxKeepAliveRequests: The maximum number of HTTP requests which can be pipelined until the connection is closed by the server. Setting this attribute to 1 will disable HTTP/1.0 keep-alive, as well as HTTP/1.1 keep-alive and pipelining. Setting this to -1 will allow an unlimited amount of pipelined or keep-alive HTTP requests. If not specified, this attribute is set to 100.
int keepAlive = 1; // 开启keepalive属性. 缺省值: 0(关闭) int keepIdle = 60; // 若是在60秒内没有任何数据交互,则进行探测. 缺省值:7200(s) int keepInterval = 5; // 探测时发探测包的时间间隔为5秒. 缺省值:75(s) int keepCount = 2; // 探测重试的次数. 所有超时则认定链接失效..缺省值:9(次) setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive)); setsockopt(s, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle)); setsockopt(s, SOL_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval)); setsockopt(s, SOL_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount)); // TCP_KEEPCNT : 覆盖 tcp_keepalive_probes ; // TCP_KEEPIDLE : 覆盖tcp_keepalive_time ; // TCP_KEEPINTVL : 覆盖 tcp_keepalive_intvl int keepAlive = 1;
#cat /proc/sys/net/ipv4/tcp_keepalive_time 7200 #cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75 #cat /proc/sys/net/ipv4/tcp_keepalive_probes 9 #echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time #echo 5 > /proc/sys/net/ipv4/tcp_keepalive_intvl #echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes全局设置可更改/etc/sysctl.conf, 使用 sudo sysctl -p当即生效;(永久有效)
net.ipv4.tcp_keepalive_intvl = 20 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.tcp_keepalive_time = 60
表示实体内容的长度。浏览器经过这个字段来判断当前请求的数据是否已经所有接收。c#
因此,当浏览器请求的是一个静态资源时,即服务器能明确知道返回内容的长度时,能够设置Content-Length
来控制请求的结束。但当服务器并不知道请求结果的长度时,如一个动态的页面或者数据,Content-Length
就没法解决上面的问题,这个时候就须要用到Transfer-Encoding
字段。windows
表示传输编码。
还有一个相似的字段叫作:Content-Encoding
。区别是Content-Encoding
用于对实体内容的压缩编码(Content-Encoding: gzip
); Transfer-Encoding
则改变了报文的格式。
当服务端没法知道实体内容的长度时,可指定Transfer-Encoding:chunked
(还可同时指定Transfer-Encoding: gzip
),
代表实体内容数据不只是gzip压缩的,仍是分块传递的。最终当浏览器接收到一个长度为0的chunked时, 标识当前请求内容已所有接收。浏览器
分块编码, 标识将数据分红一块一块的发出。Chunked编码将使用若干个Chunk串连而成,由一个标明长度为0 的chunk标示结束。
chunk-size指定十六进制的数字表明后面chunk-data的字节长度,若是是“0”,则表示chunk-size为0,该chunk为last-chunk,无chunk-data部分。服务器
Chunked-Body = *chunk //0至多个chunk last-chunk //最后一个chunk trailer //尾部 CRLF //结束标记符 chunk = chunk-size [ chunk-extension ] CRLF chunk-data CRLF // 单个chunk内容 chunk-size = 1*HEX last-chunk = 1*("0") [ chunk-extension ] CRLF chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) chunk-ext-name = token chunk-ext-val = token | quoted-string chunk-data = chunk-size(OCTET) trailer = *(entity-header CRLF)
一、Content-Length若是存在而且有效的话,则必须和消息内容的传输长度彻底一致。(若是太短则会截断,过长则会致使超时)socket
二、若是存在Transfer-Encoding(重点是chunked),则在header中的Content-Length会被忽视。tcp
三、若是采用短链接,则直接能够经过服务器关闭链接来肯定消息的传输长度。