实战 HTTP 连接管理

标签: http 管理 | 发表时间:2022-07-14 16:32 | 作者:前端程序员可乐君
出处:https://juejin.cn/frontend

1.背景

  • 短连接

HTTP 协议最初(0.9/1.0)是个非常简单的协议,通信过程也采用了简单的“请求 - 应答”方式。它底层的数据传输基于 TCP/IP,每次发送请求前需要先与服务器建立连接,收到响应报文后会立即关闭连接,所以就被称为“短连接”(short-lived connections)。

短连接的缺点相当严重,因为在 TCP 协议里,建立连接和关闭连接都是非常“昂贵”的操作。

  • 长连接

针对短连接暴露出的缺点,HTTP 1.1 版本协议就提出了“长连接”的通信方式,也叫“持久连接”(persistent connections)、“连接保活”(keep alive)、“连接复用”(connection reuse)。

15.png

2.实战

注意:以下的结果都是基于 HTTP/1.1 协议。

2.1 长短连接的特点

HTTP 1.1 默认会开启长连接,相应的头字段为 Connection,它可能会出现在请求头和相应头中。请求头中出现 Connection:keep-alive,表示客户端希望和服务器进行长连接,而响应头中使用了 Connection:keep-alive 表示最后确实是用了长连接。

我们此次实战后端使用 JavaScript 的服务端框架 Koa。接下来使用一个简单的实例来演示:

  • 后端
  const Koa = require('koa')
const app = new Koa()

app.use(async (ctx,next) => {
    ctx.body = 'hello'
})

app.listen(3002)

启动后端服务,使用浏览器打开 http://localhost:3002,我们来观察请求头和响应头。

16.png

17.png

在上面的图片中,我们可以观察客户端想要使用长连接,服务器支持并且允许开启了长连接。

接下来我们来修改一下代码:

  • 后端
  const Koa = require('koa')
const app = new Koa()

app.use(async (ctx,next) => {
    ctx.set('Connection','close')
    ctx.body = 'hello'
})

app.listen(3002)

服务端对所有请求采用短连接的方式。我们来观察一下结果。

18.png

此时虽然客户端想使用长链接,但是服务器最后策略使用了短链接。

2.2 长链接和短链接的区别

长链接可以进行链接复用。我们接下来使用代码来演示。

  • 后端 demo 结构
  projectRoot
|
|_static
       |
       |_test.html
       |_test1.png
       .
       .
       .
       |_test9.png
|
|_app.js

我们在 static 文件夹中放了 10 个文件,分别是 test.html 和 9 张图片。

  • app.js
  const Koa = require('koa')
const fs = require('fs')
const path = require('path')
const app = new Koa()


app.use(async (ctx,next) => {
    // 拿到静态文件夹的路径
    const staticPath = path.resolve(__dirname,'static')
    if(ctx.url === '/'){
        // 根路径时返回 test.html 文件
        const indexPagePath = staticPath + '/test.html'
        ctx.set('Content-Type','text/html');
        ctx.body = fs.readFileSync(indexPagePath)
    }else {
        if(ctx.url.includes('test')){
            // /testx.png 返回图片
            ctx.set('Content-Type','image/png');
            ctx.body = fs.readFileSync(staticPath + ctx.url)
        }
    }
})

app.listen(3002)
  • test.html
  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<img src="/test1.png"/>
<img src="/test2.png"/>
<img src="/test3.png"/>
<img src="/test4.png"/>
<img src="/test5.png"/>
<img src="/test6.png"/>
<img src="/test7.png"/>
<img src="/test8.png"/>
<img src="/test9.png"/>
</body>
</html>

接下来启动后端服务,使用浏览器打开 http://localhost:3002/test.html ,并且打开谷歌浏览器的开发者工具 Network 面板。注意,为了更好的观察现象,我们需要将网络模拟 Fast 3G,并且显示抓包表头项里面的 Connection ID 项,以及只看图片 Img 类型。

19.png

21.png

观察上面的结果,我们可以发现 Connection ID 有六个不同的 Id,剩下的三个 Id 是重复的。这个可以说明,chrome 浏览器在一个域名下只能同时创建 6 个 TCP 链接并发进行数据传输,剩下三个多余的请求为了复用 TCP 链接需要等待,我们通过 waterfall 表头也能观察到灰色的等待时间(stalled)。

接下来我们修改一下代码:

  • app.js
  app.use(async (ctx,next) => {
    const staticPath = path.resolve(__dirname,'static')
    if(ctx.url === '/'){
        const indexPagePath = staticPath + '/test.html'
        ctx.set('Content-Type','text/html');
        ctx.body = fs.readFileSync(indexPagePath)
    }else {
        if(ctx.url.includes('test')){
            ctx.set('Connection','close');// 使用短链接
            ctx.set('Content-Type','image/png');
            ctx.body = fs.readFileSync(staticPath + ctx.url)
        }
    }
})

20.png

服务端使用短链接之后,我们发现 Connection ID 不再重复。

2.3 长链接优化

由于长时间进行连接是很消耗服务器性能的,当链接没有数据传输或者 TCP 链接的请求数到达一定数量时,我们想要关闭长链接,这时候应该怎么做呢?

我们可以通过配置 nginx,如果配置了“keepalive_timeout 60”和“keepalive_requests 5”,意思是空闲连接最多 60 秒,最多发送 5 个请求。所以,如果连续刷新五次页面,就能看到响应头里的“Connection: close”了。

相关 [http 管理] 推荐:

实战 HTTP 连接管理

- - 掘金 前端
HTTP 协议最初(0.9/1.0)是个非常简单的协议,通信过程也采用了简单的“请求 - 应答”方式. 它底层的数据传输基于 TCP/IP,每次发送请求前需要先与服务器建立连接,收到响应报文后会立即关闭连接,所以就被称为“短连接”(short-lived connections). 短连接的缺点相当严重,因为在 TCP 协议里,建立连接和关闭连接都是非常“昂贵”的操作.

HTTP 连接管理进化论

- - SegmentFault 最新的文章
连接管理是一个 HTTP 的关键话题:打开和保持连接在很大程度上影响着网站和 Web 应用程序的性能. 在 HTTP/1.x 里有好些个模型: 短连接(short-lived connections), 持久连接(persistent connections), 和 HTTP 管道(HTTP pipelining).

管理好页面图片,减少页面加载时http连接,优化页面

- - ITeye博客
浏览器渲染页面的时候,遇到图片标签或者css中的背景图片设置,先会到本地缓存中寻找是否已经下载了这张图片,如果已经下载过了就直接从缓存中加载;否则会到图片指定的路径下载到本地缓存. 而且这种下载是阻塞式的(部分浏览器内核已经实现异步加载图片. 也就是说在下载这些图片的时候,页面渲染处于暂停状态,必须等到图片下载完成了再继续渲染.

HTTP Headers 入门

- johnny - Time Machine
非常感谢 @ytzong 同学在twitter上推荐这篇文章,原文在此. 本文系统的对HTTP Headers进行了简明易懂的阐述,我仅稍作笔记. 什么是HTTP Headers. HTTP是“Hypertext Transfer Protocol”的所写,整个万维网都在使用这种协议,几乎你在浏览器里看到的大部分内容都是通过http协议来传输的,比如这篇文章.

HTTP基础

- - ITeye博客
HTTP的结构主要包括下面几个要点:. HTTP的版本主要有1.0,1.1 和更高版本.    1.1 及以上版本允许在一个TCP连接上传送多个HTTP协议,1.0能 .    1.1 及以上版本多个请求和响应可以重叠,1.0不能.    1.1 增加了很多的请求头和响应头.     一个请求行,若干小心头,以及实体内容,其中的一些消息头和实体内容是可选的,消息头和实体内容需要空行隔开.

HTTP Header 详解

- - 博客园_Ruby's Louvre
HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议. HTTP协议采用了请求/响应模型,浏览器或其他客户端发出请求,服务器给与响应. 就整个网络资源传输而言,包括message-header和message-body两部分. 首先传递message- header,即 http header消息.

HTTP/2 in Netty

- -
Here, we created a context for the server with a JDK SSL provider, added a couple of ciphers, and configured the Application-Layer Protocol Negotiation for HTTP/2..

HTTP负载测试

- - 博客 - 伯乐在线
英文原文: ON HTTP LOAD TESTING 来源: oschina. 有很多人在谈论HTTP服务器软件的性能测试,也许是因为现在有太多的服务器选择. 这很好,但是我看到有人很多基本相同的问题,使得测试结果的推论值得怀疑. 在日常工作中花费了很多时间在高性能代理缓存和源站性能测试方面之后,这里有我认为比较重要的一些方面来分享.

HTTP断点续传

- - CSDN博客互联网推荐文章
要实现断点续传的功能,通常都需要客户端记录下当前的下载进度,并在需要续传的时候通知服务端本次需要下载的内容片段. HTTP1.1协议(RFC2616)中定义了断点续传相关的HTTP头 Range和Content-Range字段,一个最简单的断点续传实现大概如下:.   1.客户端下载一个1024K的文件,已经下载了其中512K.

http-kit 1.2 发布

- - 开源中国社区最新新闻
Http-kit 是主要由Java 和Clojure开发,为Clojure定制的零依赖的Http lib,包括异步的高性能HTTP Server 和 HTTP Client. 在普通的PC上进行性能测试时,http-kit server 每秒能处理数万个请求. 修复处理文件上传时,content-type没能正确处理.