应用层

应用层

应用层概述

应用层的作用是为应用进程之间的通讯和交互制定规则。数据单元是报文。

HTTP 超文本传输协议

http 的特点
  • 无状态:协议对客户端没有状态存储,对事物处理没有“记忆”能力,比如访问一个网站需要反复进行登录操作
  • 无连接:HTTP/1.1 之前,由于无状态特点,每次请求需要通过 TCP 三次握手四次挥手,和服务器重新建立连接。比如某个客户机在短时间多次请求同一个资源,服务器并不能区别是否已经响应过用户的请求,所以每次需要重新响应请求,需要耗费不必要的时间和流量。
  • 基于请求和响应:基本的特性,由客户端发起请求,服务端响应
  • 简单快速、灵活
  • 通信使用明文、请求和响应不会对通信方进行确认、无法保护数据的完整性

请求和响应报文

请求报文
  1. 第一行是请求方法、URL、版本协议
  1. 首部
  1. 空行分隔首部和主体
  1. 内容主体
GET http://www.example.com/ HTTP/1.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cache-Control: max-age=0 Host: www.example.com If-Modified-Since: Thu, 17 Oct 2019 07:18:26 GMT If-None-Match: "3147526947+gzip" Proxy-Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 xxx param1=1&param2=2
响应报文
  1. 第一行是版本协议、状态码及描述
  1. 首部
  1. 空行分隔首部和主体
  1. 响应的主体
HTTP/1.1 200 OK Age: 529651 Cache-Control: max-age=604800 Connection: keep-alive Content-Encoding: gzip Content-Length: 648 Content-Type: text/html; charset=UTF-8 Date: Mon, 02 Nov 2020 17:53:39 GMT Etag: "3147526947+ident+gzip" Expires: Mon, 09 Nov 2020 17:53:39 GMT Keep-Alive: timeout=4 Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT Proxy-Connection: keep-alive Server: ECS (sjc/16DF) Vary: Accept-Encoding X-Cache: HIT <!doctype html> <html> <head> <title>Example Domain</title> // 省略... </body> </html>
URL
URL 全称统一资源定位符,他是 URI(统一资源标识符)的子集,用于定位资源的路径。

HTTP 方法

  • GET 获取资源
  • POST 传送数据
  • DELETE 删除资源
  • PUT 上传文件。
    • 由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般不使用该方法。
  • HEAD
  • PATCH 对资源进行部分修改
  • OPTIONS
  • CONNECT
  • TRACE

HTTP 状态码

  • 1xx 信息
    • 100 目前为止一切正常, 客户端应该继续请求
    • 101 正在切换协议,常见 websocket
  • 2xx 成功
    • 200 请求成功
    • 204 表示该请求已经成功了,但是客户端客户不需要离开当前页面
  • 3xx 重定向
    • 301 永久重定向
    • 302 临时重定向
    • 303 和 302 有着相同的功能,但是 303 明确要求客户端应该采用 GET 方法获取资源。
    • 304 服务端已经执行了 GET,但文件未变化,也就是说可以使用缓存的内容。
  • 4xx 客户端错误
    • 400 请求报文存在语法错误
    • 403 请求被拒绝
    • 404 资源不存在
  • 500 服务器错误
    • 500 服务器正在执行请求时发生错误
    • 503 服务器暂时处于超负荷或停机维护

HTTP 首部

有 4 种类型的首部字段:通用首部字段、请求首部字段、响应首部字段和实体首部字段。
各种首部字段及其含义如下(不需要全记,仅供查阅):

通用首部字段

请求首部字段

响应首部字段

实体首部字段

短连接与长连接

当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问的 HTML 页面资源,还会请求图片资源。如果每进行一次 HTTP 通信就要新建一个 TCP 连接,那么开销会很大。
长连接只需要建立一次 TCP 连接就能进行多次 HTTP 通信。
  • 从 HTTP/1.1 开始默认是长连接的,如果要断开连接,需要由客户端或者服务器端提出断开,使用 Connection : close
  • 在 HTTP/1.1 之前默认是短连接的,如果需要使用长连接,则使用 Connection : Keep-Alive

Cookie

HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。
Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API(本地存储和会话存储)或 IndexedDB。

用途

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

创建过程

服务器发送的响应报文包含 Set-Cookie 首部字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: yummy_cookie=choco Set-Cookie: tasty_cookie=strawberry [page content]
客户端之后对同一个服务器发送请求时,会从浏览器中取出 Cookie 信息并通过 Cookie 请求首部字段发送给服务器。
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: yummy_cookie=choco; tasty_cookie=strawberry

分类

  • 会话期 Cookie:浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。
  • 持久性 Cookie:指定过期时间(Expires)或有效期(max-age)之后就成为了持久性的 Cookie。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

作用域

Domain 标识指定了哪些主机可以接受 Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了 Domain,则一般包含子域名。例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如 developer.mozilla.org)。
Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F (“/”) 作为路径分隔符,子路径也会被匹配。例如,设置 Path=/docs,则以下地址都会匹配:
  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

JavaScript

浏览器通过 document.cookie 属性可创建新的 Cookie,也可通过该属性访问非 HttpOnly 标记的 Cookie。
document.cookie = "yummy_cookie=choco"; document.cookie = "tasty_cookie=strawberry"; console.log(document.cookie);

HttpOnly

标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。跨站脚本攻击 (XSS) 常常使用 JavaScript 的 document.cookie API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

Secure

标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。

Session

除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。
Session 可以存储在服务器上的文件、数据库或者内存中。也可以将 Session 存储在 Redis 这种内存型数据库中,效率会更高。
使用 Session 维护用户登录状态的过程如下:
  • 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中;
  • 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID;
  • 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中;
  • 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。
应该注意 Session ID 的安全性问题,不能让它被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 Session ID 值。此外,还需要经常重新生成 Session ID。在对安全性要求极高的场景下,例如转账等操作,除了使用 Session 管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。

HTTP 缓存

HTTPS

HTTP2

HTTP2 的目标是提高传输性能。
http2 的特点
  • 多路复用
  • 二进制协议
  • 首部压缩
  • 流的优先级
  • 流量控制
  • 服务器推送

二进制协议

http1.1 是基于文本的,而 http2 则是基于二进制的,http 消息被定义成数据帧发送。

多路复用

http1.1 是一种同步的、请求-响应式的协议,一条连接中当发送一条请求后,需要等待接收完响应后才能发送另一条请求,这种方式效率低下。
而 http2 实现了多路复用,即允许单条连接上同时执行多条请求。
http2 通过使用二进制分帧层,将一条请求或响应封装成帧,并标上一个流(消息)的标识符,发送方可以将多条请求同时发送出去,当接收方接收一条流的所有帧后,可以将帧合成完整的消息。
http2 提高效率的重点在于他不用等待响应接收后才能发送下一个请求,而是可以变接收响应边发送请求,这样的效率更高。

Get 与 Post 的区别

  • get 方法如果不改变 url,可能会存在缓存问题,一般会在后面加上时间戳来重新加载。
  • get 请求参数是放在 url 中,而 post 参数是放到请求体里。
  • post 方式请求时,需要设置编码类型,一般是在请求头里的content-type里设置,值有application/x-www-form-urlencodedapplication/jsonmultipart/formdata等格式。
  • get 主要是用作获取数据,而 post 是修改数据
  • get 的参数是放到 url 中,也就是说参数的长度取决于浏览器的 url 限制长度。

DNS 域名系统

DNS 全称域名系统,他的作用是实现 ip 地址与域名的互转。
DNS 传输使用的是 UDP,这样能减少性能开销,此外域名服务器还设有缓存,会将查询结果缓存一定时间,来减少查询次数。
域名系统查询过程(迭代)
  • 浏览器将域名发送给本地域名服务器,并成为本地域名服务器的一个客户
  • 本地域名服务器查询根域名服务器,根域名服务器给出下一步要查询的域名服务器
  • 本地域名服务器查询顶级域名服务器,顶级域名服务器给出下一步要查询的域名服务器
  • 本地域名服务器查询二级域名服务器,二级域名服务器给出下一步要查询的域名服务器
  • ………
  • 本地服务器查询权限域名服务器,并获取主机的 ip 地址
  • 本地域名服务器将查询结果告诉主机
域名系统查询过程(递归)
  • 浏览器将域名发送给本地域名服务器,并成为本地域名服务器的一个客户
  • 本地域名服务器查询根域名服务器
  • 根域名查询顶级域名服务器
  • 顶级域名服务器查询二级域名服务器
  • 二级域名服务器查询权限域名服务器
  • 权限域名服务器查询到主机的 ip 地址,并将结果返回给二级域名服务器
  • 二级域名服务器将查询结果返回给顶级域名服务器
  • 顶级域名服务器将查询结果返回给跟域名服务器
  • 根域名服务器将查询结果返回给本地域名服务器
  • 本地域名服务器将查询结果返回给主机

CDN

CDN是指内容分发网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上,从而达到加快访问速度的目的。

CND的工作原理

CDN查询过程:
  1. 客户端本地DNS系统解析,如果没有相应域名的缓存,则本地DNS系统会将域名解析权交给CNAME指向的CDN的专用DNS服务器。
  1. CDN的DNS服务器返回全局负载均衡设备的ip地址
  1. 用户将CDN的全局负载均衡设备发起请求。
  1. 全局负载均衡设备根据用户的ip地址及请求url,选择一台用户所属区域的区域负载均衡设备,并将请求转发到此设备上。
  1. 区域负载均衡设备根据用户的ip地址、请求url及各缓存服务器的负载情况,选择出一台最佳的缓存服务器,并将此缓存服务器的ip地址返回给全局负载均衡设备
  1. 全局负载均衡设备将缓存服务器的ip地址返回给客户端。
  1. 客户端向缓存服务器发送请求,缓存服务器响应请求。如果服务器没有请求的资源,则会向上一级缓存服务器请求内容,直至追溯到向源服务器发送请求将资源拉取到本地,这一过程称为回源。

CDN的优缺点

优点
  • 解决了跨运营商、跨地区所带来的的访问慢的问题,加快资源的访问速度。
  • 缓解源服务器的压力。
  • 资源访问是通过缓存服务器而不是源服务器,在一定程度上避免了源服务器被攻击的风险。
缺点