一、概念

  HTTP 长连接,也称持久连接(HTTP persistent connection / HTTP keep-alive / HTTP connection reuse),是使用同一个 TCP 连接来发送和接收多个 HTTP 请求/应答,而不是为每个新的请求/应答打开新的 TCP 连接。这种方式下由于通讯连接一直存在,此种方式常用于 P2P 通信。

  HTTP 短连接,浏览器和服务器每进行一次 HTTP 操作,就会建立一次连接,但任务结束后就中断连接,不会像长连接那样保持连接。此方式常用于一点对多点通讯,C/S 通信。

二、长连接和短连接的操作过程

  长连接的操作步骤是:
建立连接 — — 数据传输 — — 保持连接(心跳) — — 数据传输 — — 保持连接(心跳)… — — 关闭连接

  短连接的操作步骤是:
建立连接 — — 数据传输 — — 关闭连接…建立连接 — — 数据传输 — — 关闭连接

三、长连接和短连接的使用时机

  长连接多用于操作频繁,点对点的通讯,而且连接数不能太多的情况。每个 TCP 连接的建立都需要三次握手,每个 TCP 连接的断开要四次挥手。
  如果每次操作都要建立连接然后再操作的话,处理速度会降低,所以每次操作后,下次操作时直接发送数据就可以了,不用再建立TCP连接。例如:数据库的连接用长连接。如果用短连接频繁的通信会造成 socket 错误,频繁的 socket 创建也是对资源的浪费。

  Web 网站的 http 服务一般都用短连接,因为长连接对于服务器来说要耗费一定的资源。像 web 网站这么频繁的成千上万甚至上亿客户端的连接用短连接更省一些资源。试想如果都用长连接,而且同时有成千上万的用户,每个用户都占有一个连接的话,可想而知服务器的压力有多大。所以并发量大,但是每个用户又不需频繁操作的情况下需要短连接。

  总之:长连接和短连接的选择要根据需求而定。长连接和短连接的产生在于 client 和 server 采取的关闭策略,具体的应用场景采用具体的策略,没有十全十美的选择,只有合适的选择。

四、优点和不足

  长连接优势:

  • 由于同时打开的 TCP 连接的减少,会使用较少的 CPU 和内存。
  • 允许请求和应答的 HTTP 管线化(将多个 HTTP request 整批提交的技术,而在传送过程中不需要先等待服务器的回应)。
  • 通过减少 TCP 开启引起的包的数目,降低网络阻塞。
  • 不需要进行握手,减少了后续请求的延迟。
  • 报告错误无需关闭 TCP 连接。

用户客户端与任何服务器和代理服务器之间不应该维持超过 2 个连接。代理服务器应该最多使用 2 * N 个持久连接到其他服务器或者代理服务器,其中 N 是同时活跃的用户数。旨在提高HTTP响应时间并避免阻塞。

  短连接优势:
  web 网站的 http 服务一般都用短连接。因为长连接对于服务器来说要耗费一定的资源。像 web 网站这么频繁的成千上万甚至上亿的客户端的连接用短连接更省一些资源。试想如果都用长连接,而且同时有成千上万的用户,每个用户都占有一个连接的话,可想而知服务器的压力有多大。所以并发量大,但是每个用户又不需频繁操作的情况下需要短连接。总之,长连接和短连接的选择要根据需求而定。

  长连接劣势:
  对于现在的广泛普及的宽带连接来说,Keep-Alive 也许并不像以前一样有用。web 服务器会保持连接若干秒(取决于 Apache 等 web 服务器的配置),这与提高的性能相比也许会影响性能。
  对于单个文件被不断请求的服务(例如图片存放网站),Keep-Alive 可能会极大的影响性能,因为它在文件被请求之后还保持了很长时间不必要的连接。

  短连接劣势:
  如果用短连接频繁的通信会造成 socket 错误,而且频繁的 socket 创建也是对资源的浪费。

五、http 长连接设置
5.1 HTTP 1.0 设置

  在 HTTP1.0 官方协议中并没有对 keepalive 的明确支持,如果要在 HTTP1.0 中支持 keepalive,必须明确的在 header 中加入 Connection:keep-alive,过程如下。

  1. client 发起一个包含 Connection:keep-alive 的请求。
  2. server 收到请求后,如果 server 支持 keepalive,回复一个包含 Connection:keep-alive 的响应,不关闭连接;否则回复一个包含 Connection:close 的响应,关闭连接。
  3. 如果 client 收到包含 Connection:keep-alive 的响应,向同一个连接发送下一个请求,直到一方主动关闭连接。
5.2 HTTP 1.1 设置

  因为 keepalive 在很多情况下能够重用连接,减少资源消耗,缩短响应时间,所以在 HTTP1.1 中缺省就是支持 keepalive 的。如果响应方不支持 keepalive,需要在应答报文头中明确的标识 Connection:close,那么客户端设置的 Connection:keep-alive 就失效了。

  设置 HTTP 短连接:
  在应答报文头中设置 Connection:close,则在一次请求/响应之后,就会关闭连接。

  设置 HTTP 长连接,有过期时间:
  在应答报文头中设置 Connection:keep-alive 和 Keep-Alive: timeout=60,表明连接建立之后,空闲时间超过60秒之后,就会失效。如果在空闲第 58 秒时,再次使用此连接,则连接仍然有效,使用完之后,重新计数,空闲 60 秒之后过期。

  设置 HTTP 长连接,无过期时间:
  在应答报文头中只设置 Connection:keep-alive,表明连接永久有效。

六、HTTP 长连接实现原理及配置案例

  了解怎么设置长连接之后,就开始用起来。然而,问题来了,在请求头中设置 Connection:keep-alive,为什么连接空闲一段时间之后,还是断开了呢?这是因为 Connection 字段只有服务端设置才有效。
  HTTP 操作是请求/响应成对出现的,即先有客户端发出请求,后有服务端处理请求。所以,一次 HTTP 请求的终点操作在服务端上,关闭也是由服务端发起的。

  接下来举几个配置案例。

6.1 客户端连接失效时间大于服务端失效时间

  客户端设置 Connection: Keep-Alive 和 Keep-Alive: timeout=60。
  服务端设置 Connection: Keep-Alive 和 Keep-Alive: timeout=5。
  当客户端设置的有效期大于服务端设置的有效期,此时服务端的设置生效,连接的实际有效时间是根据 response 的设置来决定的。

6.2 客户端设置Connection: Close

  如上,当客户端设置的是短连接时,服务端返回的也是 Connection: Close,客户端接收完响应,便会关闭连接。
  另外,不论 request 还是 response 的 header 中包含了值为 close 的 Connection,都表明当前正在使用的 tcp 连接在请求处理完毕后会被断掉。以后 client 再进行新的请求时就必须创建新的 tcp 连接了。HTTP Connection 的 close 设置允许客户端或服务器中任何一方关闭底层的连接,双方都会要求在处理请求后关闭它们的 TCP 连接。

6.3 客户端设置失效时间,服务端设置不失效

  客户端设置 Connection: keep-alive 和 Keep-Alive: timeout=30。
  服务端设置永久连接,即 Connection: keep-alive。
  连接将一直保持。