目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

HTTP协议概念

HTTP 协议应用的场景分析

应用场景

  1. 用户界面中,即浏览器 URL 地址栏中输入地址。
  2. 当地址还没有输入完整,浏览器引擎会从本地数据存储中查询历史数据,以便智能补全输入的完整地址。
  3. 按下 Enter 键后会由渲染引擎通过网络发起首次 HTTP 请求。
  4. 服务端响应 HTML 包体至客户端浏览器,渲染引擎接收到响应,并解析包体内容渲染至用户界面,并根据包体内的超链接构建新的 HTTP 请求,例如:js、CSS 等不同种类的超链接。
  5. 接收到服务端的响应,并交给对应的解释器,例如:JS 解释器
  6. 渲染引擎拿到所需的所有文件后,通过 UI 后端绘制到用户界面中。

一次完整的 HTTP 请求流程

HTTP 请求流程

Chrome 浏览器 Network 面板

Chrome 抓包

Hypertext Transfer Protocol (HTTP) 协议

a stateless application-level request/response protocol that uses extensible semantics and self-descriptive message payloads for flexible interaction with network-based hypertext information systems(RFC7230 2014.6)
一种无状态的、应用层的、以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动。

  • 无状态:后一个请求不能依赖前一个请求中的字段或头部信息。
  • 请求/响应:基于一个连接由客户端发起请求,服务器端响应的模式。
  • 可扩展语义:服务器还在使用 HTTP1.0 协议,而客户端浏览器支持 HTTP1.1 协议,客户端和浏览器之间依然可以正常通讯。
  • 字描述消息格式:从传送的消息本身就可以知道消息的是什么类型的,不需要依赖于额外的请求。例如:音频、视频、图片等…
  • 超文本信息系统:传输的内容不仅限于文档,还有图片、音频、视频等其他内容。

HTTP 消息格式(基于 ABNF 语义)

HTTP 消息格式
ABNF (扩充巴科斯-瑙尔范式)操作符
ABNF 操作符
ABNF (扩充巴科斯-瑙尔范式)核心规则
ABNF 核心规则
基于 ABNF 描述的 HTTP 协议格式
ABNF 描述的 HTTP 协议格式

OSI(Open System Interconnection Reference Model)概念模型

OSI 概念模型

  • 应用层:解决业务问题。HTTP、FTP、SMTP、DNS、P2P 等……
  • 表示层:负责将网络中消息转换成应用层可以读取的消息。TLS、SSL。
  • 会话层:负责建立会话,握手、维持连接、关闭连接。传输层与表示层都有部分延伸到会话层。
  • 传输层:解决进程与进程之间的通信。在网络通信中,必须将 IP 地址和端口地址结合起来才能实现应用进程之间的通信。
  • 网络层:解决广域网中主机与主机之间的通信。IP 地址。
  • 数据链路层:以太网等类似局域网中主机与主机之间的通信。
  • 物理层:定义物理介质。

OSI 与 TCP/IP 模型分层的系统

OSI 与 TCP/IP 模型分层
优点
 利于每层的扩展和修改,不会影响到其他层,只要遵循约定好的接口即可。
缺点
 通信的数据需用从到下经过网络传输到目的地再进行从下到上的过程,严重影响性能。 为了解决性能问题,衍生出一些相应的库 DPDK:其主要原理就是绕过下层。 导致的问题:操作系统上一些 DEBUG 工具调试工具在打开 DPDK 之后都是无法使用的。
 (Data Plane Development Kit)是由 6WIND,Intel 等多家公司开发,主要基于 Linux 系统运行,用于快速数据包处理的函数库与驱动集合,可以极大提高数据处理性能和吞吐量,提高数据平面应用程序的工作效率。

网络分层抓包分析

分层抓包
报文头部解析
报文头部
CS:Frame Check Sequence(帧校验序列)
 俗称帧尾,即计算机网络数据链路层的协议数据单元(帧)的尾部字段,是一段 4 个字节的循环冗余校验码。源节点发送数据帧时,由帧的帧头和数据部分计算得出 FCS,目的节点接收到后,用同样的方式再计算一遍 FCS,如果与接收到的 FCS 不同,则认为帧在传输过程中发生了错误,从而选择丢弃这个帧。

From Follows Function: 为什么这样设计?

 Web's major goal was to be a shared information space through which people and machines could communicate. --Tim Berners Lee
HTTP 必须面对以下非功能性的需求:

  • 低门槛:开发者与使用者容易上手。
  • 可扩展性:巨大的用户群体,超长的寿命
  • 分布式系统下的 Hypermedia:大粒度数据的网络传输
  • Internet 规模
    无法控制的 scalability
       不可预测的负载、非法格式的数据、恶意消息
       客户端不能保持所有服务器信息,服务器不能保持多个请求间的状态信息
    独立的组件部署:新老组件并存
  • 向前兼容:自 1993 年起 HTTP0.9\1.0(1996)已经被广泛使用

评估 Web 架构的关键属性

HTTP 协议应当在以下属性中取得可接受的均衡

  1. 性能 Performance:影响高可用的关键因素
  2. 可伸缩性 Scalability:支持部署可以互相交互的大量组件
  3. 简单性 Simplicity:易理解、易实现、易验证
  4. 可见性 Visiable:对两个组件间的交互进行监视或者仲裁的能力。如缓存、分层设计等
  5. 可移植性 Portability:在不同的环境下运行的能力
  6. 可靠性 Reliability:出现部分故障时,对整体影响的程度
  7. 可修改性 Modifiability:对系统作出修改的难易程度,由可进化性、可定制性、可扩展性、可配置性、可重用性构成

架构属性:性能

  • 网络性能 Network Performance
     Throughput 吞吐量:小于等于带宽 bandwidth
     Overhead 开销:首次开销,每次开销
  • 用户感知到的性能 User-perceived Performance
     Latency 延迟:发起请求到接收到响应的时间
     Completion 完成时间:完成一个应用动作所花费的时间
  • 网络效率 Network Efficiency
     重用缓存、减少交互次数、数据传输距离更近、COD

架构属性:可修改性

  • 可进化性 Evolvability:一个组件独立升级而不影响其他组件
  • 可扩展性 Extensibility :向系统添加功能,而不会影响到系统的其他部分
  • 可定制性 Customizability :临时性、定制性地更改某一要素来提供服务,不对常规客户产生影响
  • 可配置性 Configurability:应用部署后可通过修改配置提供新的功能
  • 可重用性 Reusabilit :组件可以不做修改在其他应用在使用

Uniform Resource Identifier 统一资源标识符

当没有 URI 时
站长 A 欲分享一部电影 Forrest Gump 给 B,需要告诉:

  • 请使用 FTP 协议访问 mysite.net,端口是 8502
  • 登录用户名是 user,密码 pass
  • 进入到 /shared/movie 目录下
  • 转换为二进制模式
  • 下载名为 Forrest Gump.mkv 格式的文件

使用 URI 进行资源共享
 ftp://user:pass@mysite.net:8502/shared/movie/Forrest Gump.mkv

URI 概念
 Uniform Resource Identifier,用以区分资源,是 URL 和 URN 的超集,用以取代 URL 和 URN 概念。

URI 的组成
URI 的组成

为什么要进行 URI 编码

  • 传递数据中,如果存在用作分隔符的保留字符怎么办?
    https://www.baidu.com/s?wd=?#!
  • 对可能产生歧义性的数据编码
     不在 ASCII 码范围内的字符
     ASCII 码中不可显示的字符
     URI 中规定的保留字符
     不安全字符(传输环节中可能会被不正确处理),如空格、引号、尖括号等

请求行

请求行
Method
• GET:主要的获取信息方法,大量的性能优化都针对该方法,幂等方法
• HEAD:类似 GET 方法,但服务器不发送 BODY,用以获取 HEAD 元数据,幂等方法
• POST:常用于提交 HTML FORM 表单、新增资源等
• PUT:更新资源,带条件时是幂等方
• DELETE:删除资源,幂等方法
• CONNECT:建立 tunnel 隧道
• OPTIONS:显示服务器对访问资源支持的方法,幂等方法
• TRACE:回显服务器收到的请求,用于定位问题。有安全风险
request-target
 request-target = origin-form / absolute-form / authority-form / asterisk-form
HTTP-version
• HTTP/0.9:只支持 GET 方法,过时
• HTTP/ 1.0:RFC1945,1996, 常见使用于代理服务器(例如 Nginx 默认配置)
• HTTP/ 1.1:RFC2616,1999
• HTTP/ 2.0:2015.5 正式发布

响应行

响应行
• 1xx:请求已接收到,需要进一步处理才能完成,HTTP1.0 不支持
• 2xx:成功处理请求
• 3xx:重定向使用 Location 指向的资源或者缓存中的资源。在 RFC2068
• 4xx:客户端出现错误
• 5xx:服务器端出现错误

HTTP 连接流程

HTTP 连接流程
从 TCP 编程视角看 HTTP 请求处理
从 TCP 编程视角看 HTTP 请求处理

短连接与长连接

短连接与长连接
客户端与服务器中间通过携带 Connection 头部来建立长连接。

  • 客户端请求长连接:Conection: Keep-Alive
  • 服务器表示支持长连接:Conection: Keep-Alive
  • HTTP/1.1 默认支持长连接,因此在携带 Conection: Keep-Alive 头部是无意义的。
  • 短连接:Conection: Close
  • 代理服务器不转发 Connection: XXX 中列出的头部,该头部仅与当前连接相关。

全链路支持长连接的情况
全链路支持长连接

链路中存在不支持长连接的正向代理服务器的情况
链路中存在不支持长连接的代理服务器

  • 客户端发起请求携带 Conection: Keep-Alive
  • 代理服务器陈旧,不能正确处理 Conection 头部,因而将客户端请求中的 Conection: Keep-Alive 原封不动的转发给上游服务器。
  • 上游服务器正确处理了 Connection 头部,响应代理服务器 Conection: Keep-Alive 表示支持长连接,并在响应后没有关闭连接,而试图保持、复用与不能识别长连接的代理服务器所建立的连接。
  • 代理服务器收到响应中的 Conection: Keep-Alive,因为不能正确处理 Conection: Keep-Alive,所以转发给客户端,同时等待服务器关闭短连接。
  • 客户端收到了 Conection: Keep-Alive,认为可以复用与代理服务器之间的长连接,继续在该连接上发起请求。
  • 代理服务器出错,因为短连接无法发起两次请求。

链路中存在陈旧正向代理服务器的结局方案——Proxy-Connection: Keep-Alive

  • 陈旧的代理服务器不识别该头部:因为完全不能识别,所以退化为短连接。
  • 新版本的代理服务器理解该头部:与客户端建立连接、并在转发至服务器时使用 Connection: Keep-Alive 代替 Proxy-Connection: Keep-Alive 头部。

Host 与消息的路由

  • HTTP/1.1 规范要求,不传递 Host 头部则返回 400 错误响应码。
  • 发送超过一个以上的 Host 头部,则返回 400 错误响应码。
  • Host 中头部中的值是不合法的,则返回 400 错误响应码。
  • 为防止陈旧的代理服务器,发向正向代理的请求 request-target 必须以 absolute-form 形式出现。
      request-line = method SP request-target SP HTTP-version CRLF

Host 与消息的路由

代理服务器转发消息时相关头部处理

如何传递 IP

  • Max-Forwards 头部
     限制 Proxy 代理服务器的最大转发次数,仅对 TRACE/OPTIONS 方法有效。
     Max-Forwards = 1 *DIGIT
  • Via 头部
     指明经过的代理服务器名称及版本
  • Cache-Control:no-transform
     禁止代理服务器修改响应包体。

请求与响应的上下文头部

  • User-Agent :指明客户端的相关信息,用于帮助服务器对资源的表述做抉择。 例如:User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
  • Referer : 浏览器对来自某一页面的请求自动添加的头部。 服务器端常用于统计分析、缓存优化、防盗链等功能。例如:Referer: https://developer.mozilla.org/zhCN/docs/Web/HTTP/Headers/User-Agent
     Referer 不会被添加的场景:来源页面采用的协议为表示本地文件的 "file" 或者 "data" URI、当前请求页面采用的是 http 协议,而来源页面采用的是 https 协议。
  • From : 主要用于网络爬虫,告诉服务器如何通过邮件联系到爬虫的负责人。
     From = mailbox
     例如: From: webmaster@example.org
  • Server : 指明服务器上所用软件的信息,用于帮助客户端定位问题或者统计数据。
     例如:Server: nginx 或 Server: openresty/1.13.6.2
  • Allow : 告诉客户端,服务器上该 URI 对应的资源允许哪些方法的执行
     例如:Allow: GET, HEAD, PUT
  • Accept-Ranges :告诉客户端服务器上该资源是否允许 range 请求。(多线程下载和断点续传场景),告诉客户端接下来的请求可以使用什么样的协商方式。
     例如:Accept-Ranges: bytes (接受) 或 Accept-Ranges: none (不接受)

作者:Soulboy