网络知识相关

Posted by Qz on January 19, 2019

“Yeah It’s on. ”

网络协议

https://mp.weixin.qq.com/s/6DBhbz7eAETXVbPHmOKHww

HTTP1.1

如果页面中发起了多个http请求,此时只需要建立一个tcp连接就可以了,多个http请求响应会共用这一个tcp连接通道。

相比1.0,优势在于:

  • 增加持久性连接
  • 增加管道机制
  • 分块传输
  • 增加 host 字段
  • 错误提示
  • 带宽优化

管道化

https://cloud.tencent.com/developer/article/1509279

管线化机制须通过永久连接(persistent connection)完成,仅HTTP/1.1支持此技术(HTTP/1.0不支持)

在使用持久连接的情况下,某个连接消息的传递类似于

  • 请求1 -> 响应1 -> 请求2 -> 响应2

管线化:某个连接上的消息变成了类似这样

  • 请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3

图片

持久连接的一个缺点是请求和响应式是顺序执行的,只有在请求1的响应收到之后,才会发送请求2,而管线化不需要等待上一次请求得到响应就可以进行下一次请求。实现并行发送请求。

只有GET和HEAD要求可以进行管线化,而POST则有所限制

管道化要求服务端按照请求发送的顺序返回响应(FIFO),原因很简单,HTTP请求和响应并没有序号标识,无法将乱序的响应与请求关联起来。

当客户端在支持管道化时需要保持未收到响应的请求,当连接意外中断时,需要重新发送这部分请求。如果这个请求只是从服务器获取数据,那么并不会对资源造成任何影响,而如果是一个提交信息的请求如post请求,那么可能会造成资源多次提交从而改变资源,这是不允许的。而不会对服务器资源产生影响的请求有个专业名词叫做幂等请求。客户端在使用管道化的时候请求方式必须是幂等请求。

因为HTTP管道化本身可能会导致队头阻塞的问题,以及上面提到的一些限制,现代浏览器默认都关闭了管道化,并且大部分服务器也是默认不支持管道化的

带宽优化

HTTP/1.1 中在请求消息中引入了 range头域,它允许只请求资源的某个部分。

在响应消息中 Content-Range头域声明了返回的这部分对象的偏移值和长度。如果服务器相应地返回了对象所请求范围的内容,则响应码为 206(PartialContent),它可以防止 Cache将响应误以为是完整的一个对象,HTTP/1.1 加入了一个新的状态码 100(Continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码 401(Unauthorized);如果服务器接收此请求就回送响应码 100,客户端就可以继续发送带实体的完整请求了。

注意,HTTP/1.0 的客户端不支持 100 响应码。但可以让客户端在请求消息中加入 Expect头域,并将它的值设置为 100-continue

HTTP1.1的缺陷

  • 高延迟 — 队头阻塞(Head-Of-Line Blocking)
  • 无状态特性 — 阻碍交互
  • 明文传输 — 不安全性
  • 不支持服务端推送

队头阻塞

队头阻塞是指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。

针对队头阻塞:

  1. 将同一页面的资源分散到不同域名下,提升连接上限。虽然能公用一个 TCP 管道,但是在一个管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。
  2. 减少请求数量
  3. 内联一些资源:css、base64 图片等
  4. 合并小文件减少资源数

客户端建立长连接的个数是针对域名发起的,举例说明,当我们访问a.com网站的时候,客户端与a.com服务器建立的长链接就是2个。但是一般浏览器会把并发链接数增加到6到8个,谷歌浏览器是6个


无状态特性

无状态是指协议对于连接状态没有记忆能力。纯净的 HTTP 是没有 cookie 等机制的,每一个连接都是一个新的连接。上一次请求验证了用户名密码,而下一次请求服务器并不知道它与上一条请求有何关联,换句话说就是掉登录态。


不安全性

传输内容没有加密,中途可能被篡改和劫持。

webscoket

https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

WebSocket 是基于TCP 的一种新的应用层网络协议。 它实现了浏览器与服务器全双工通信,即允许服务器主动发送信息给客户端。 因此,在WebSocket 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变得更加简单

应用层协议、基于 TCP、全双工通信、一次握手、持久连接、双向数据传输

特点:

  • 建立在 TCP 协议之上;
  • 与 HTTP 协议有着良好的兼容性:默认端口也是 80(ws) 和 443(wss,运行在 TLS 之上),并且握手阶段采用 HTTP 协议;
  • 较少的控制开销:连接创建后,ws 客户端、服务端进行数据交换时,协议控制的数据包头部较小,而 HTTP 协议每次通信都需要携带完整的头部;
  • 可以发送文本,也可以发送二进制数据;
  • 没有同源限制,客户端可以与任意服务器通信;
  • 协议标识符是 ws(如果加密,则为 wss),服务器网址就是 URL;
  • 支持扩展:ws 协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议

建立连接

在 WebSocket 开始通信之前,通信双方需要先进行握手,WebSocket 复用了 HTTP 的握手通道,即客户端通过 HTTP 请求与 WebSocket 服务端协商升级协议。协议升级完成后,后续的数据交换则遵照 WebSocket 的协议。

利用 HTTP 完成握手有什么好处呢?

一是可以让 WebSocket 和 HTTP 基础设备兼容(运行在 80 端口 或 443 端口),二是可以复用 HTTP 的 Upgrade 机制,完成升级协议的协商过程。

WebSocket是基于TCP的,TCP的握手和WebSocket的握手是不同层次的。

TCP的握手用来保证链接的建立,WebSocket的握手是在TCP链接建立后告诉服务器这是个WebSocket链接,服务器你要按WebSocket的协议来处理这个TCP链接。

Handshake

收到状态码:

101 WebSocket Protocol HandShake

101 Switching Protocols

WebSocket Protocol Handshake是指WebSocket协议的握手过程。

WebSocket是一种在Web浏览器和服务器之间进行全双工通信的协议,可以实现实时数据传输。在建立WebSocket连接之前,需要进行握手来确认浏览器和服务器是否支持WebSocket协议,并进行必要的协议升级。

在WebSocket Protocol Handshake过程中,浏览器首先发送一个HTTP请求到服务器,请求头中包含了一些WebSocket相关的信息。服务器接收到请求后,会进行验证,并返回一个HTTP响应,响应头中包含了一些关于WebSocket支持的信息。

维持连接

如果我们使用 WebSocket 进行通信,建立连接之后怎么判断连接正常没有断开或者服务是否可用呢?

可以通过建立心跳机制,所谓心跳机制,就是定时发送一个数据包,让对方知道自己在线且正常工作,确保通信有效。如果对方无法响应,便可以弃用旧连接,发起新的连接了。

使用ping/pong心跳包可以有效地监测和处理连接的状态,避免长时间的无响应或断开连接情况的发生,提高连接的稳定性和可靠性。

通信过程

  1. 握手(Handshake):客户端通过HTTP协议发送Upgrade请求头部,服务器接收到请求后回复Sec-WebSocket-Accept头部响应,并完成握手过程。

  2. 数据传输:握手成功后,客户端和服务器建立WebSocket连接,双方可以通过WebSocket协议进行双向通信。

    a. 客户端向服务器发送数据:客户端可以通过WebSocket的send()方法向服务器发送数据,数据经过WebSocket协议封装后通过TCP/IP传输到服务器。

    b. 服务器向客户端发送数据:服务器可以通过WebSocket的send()方法向客户端发送数据,数据经过WebSocket协议封装后通过TCP/IP传输到客户端。

  3. 连接关闭:客户端或服务器可以通过WebSocket的close()方法主动关闭连接,或者当连接出现错误时自动关闭。关闭连接时,双方都会收到一条关闭帧(Close Frame)。

需要注意的是,WebSocket通信过程中的数据是以二进制格式进行传输的,而不是像HTTP协议那样以文本格式传输。因此,在传输数据时,客户端和服务器需要将数据按照WebSocket协议的规定进行封装和解析。此外,WebSocket通信是一种长连接,可以保持连接状态,双方可以实时进行数据传输。

TCP

TCP是一种面向连接的协议,全称为传输控制协议(Transmission Control Protocol)。它是互联网通信中基于IP协议的一种传输层协议。

TCP通过在通信双方之间建立可靠的连接,实现可靠的数据传输。它提供了数据的序列化、可靠性检验、数据分割和重新组装、流量控制等功能。TCP采用三次握手建立连接,四次挥手断开连接,确保数据的可靠传输和有序接收。此外,TCP还支持拥塞控制机制,用于避免网络拥塞。

TCP是面向字节流的,它将报文分割成若干个数据段进行传输,并且保证这些数据段按照正确的顺序到达目的地端。

TCP连接复用(TCP Connection Reuse)

https://blog.csdn.net/gao_yu_long/article/details/79754541

TCP连接复用技术通过将前端多个客户的HTTP请求复用到后端与服务器建立的一个TCP连接上。这种技术能够大大减小服务器的性能负载,减少与服务器之间新建TCP连接所带来的延时,并最大限度的降低客户端对后端服务器的并发连接数请求,减少服务器的资源占用。

一般情况下,客户端在发送HTTP请求之前需要先与服务器进行TCP三次握手,建立TCP连接,然后发送HTTP请求。服务器收到HTTP请求后进行处理,并将处理的结果发送回客户端,然后客户端和服务器互相发送FIN并在收到FIN的ACK确认后关闭连接。在这种方式下,一个简单的HTTP请求需要十几个TCP数据包才能处理完成。

采用TCP连接复用技术后,客户端(如:ClientA)与负载均衡设备之间进行三次握手并发送HTTP请求。负载均衡设备收到请求后,会检测服务器是否存在空闲的长连接,如果不存在,服务器将建立一个新连接。当HTTP请求响应完成后,客户端则与负载均衡设备协商关闭连接,而负载均衡则保持与服务器之间的这个连接。当有其它客户端(如:ClientB)需要发送HTTP请求时,负载均衡设备会直接向与服务器之间保持的这个空闲连接发送HTTP请求,避免了由于新建TCP连接造成的延时和服务器资源耗费。

TCP粘包

TCP粘包是指在TCP连接中,发送端连续向接收端发送多个数据包,在接收端由于一次性读取数据不完整或读取数据过程中发生延迟等原因导致多个数据包被合并成一个数据块的现象。这样就会造成接收端难以正确解析数据,进而影响正常的通信。

TCP粘包可能是因为TCP协议为了提高数据传输的效率而采用的流模式传输,而不是像UDP一样按照报文进行传输。因此,在接收端需要通过额外的处理方法来正确地处理粘包现象。

常见的处理方法包括:

  1. 定长分包:发送端在发送数据包前,将数据按照固定的长度进行分包,接收端按照同样的长度来接收和解析数据。
  2. 变长分包:发送端在数据包中添加特定标识符或长度字段,接收端根据特定标识符或长度字段来定位和解析数据。
  3. 使用消息边界:每个数据包之间添加特定的消息边界,例如特定的字符或者特殊的分隔符,接收端根据消息边界来区分不同的数据包。
  4. 使用定时发送:发送端在发送数据包前,固定等待一定的时间,确保接收端能够将之前的数据包处理完毕,再进行下一次发送。这样可以避免接收端在处理数据包过程中造成粘包现象。

以上是常见的处理TCP粘包的方法,具体的处理方式可以根据实际需求和情况进行选择。

NTP

网络时间协议

https://info.support.huawei.com/info-finder/encyclopedia/zh/NTP.html

网络时间协议NTP(Network Time Protocol)是TCP/IP协议族里面的一个应用层协议,用来使客户端和服务器之间进行时钟同步,提供高精准度的时间校正。NTP服务器从权威时钟源(例如原子钟、GPS)接收精确的协调世界时UTC,客户端再从服务器请求和接收时间。

SPDY 协议

SPDY 是由 google 推行的改进版本的 HTTP1.1 (那时候还没有 HTTP2)。

特性:

  • 多路复用 — 解决队头阻塞
  • 头部压缩 — 解决巨大的 HTTP 头部
  • 请求优先级 — 先获取重要数据
  • 服务端推送 — 填补空缺
  • 提高安全性

多路复用

SPDY 允许在一个连接上无限制并发流。因为请求在一个通道上,TCP 效率更高。更少的网络连接,发出更密集的包。


头部压缩

使用专门的 HPACK 算法,每次请求和响应只发送差异头部,一般可以达到 50% ~90% 的高压缩率。


请求优先级

虽然无限的并发流解决了队头阻塞的问题,但如果带宽受限,客户端可能会因防止堵塞通道而阻止请求。在网络通道被非关键资源堵塞时,提高安全性 请求会被优先处理。


服务端推送

服务端推送(ServerPush),可以让服务端主动把资源文件推送给客户端。当然客户端也有权利选择是否接收。


提高安全性

支持使用 HTTPS 进行加密传输。

HTTP2

HTTP2 基于 SPDY,专注于性能,最大的一个目标是在用户和网站间只用一个连接。


优势

二进制分帧

首先,HTTP2 没有改变 HTTP1 的语义。因此,也引入了新的通信单位:帧、消息、流

在应用层(HTTP/2.0)和传输层(TCP or UDP)之间增加一个二进制分帧层,从而突破 HTTP1.1 的性能限制,改进传输性能实现低延迟高吞吐量

简单来说,HTTP/2.0 只是把原来 HTTP1.x 的 headerbody 部分用 frame 重新封装了一层而已。

分帧有什么好处?服务器单位时间接收到的请求数变多,可以提高并发数。最重要的是,为多路复用提供了底层支持。

图片

多路复用

一个域名对应一个连接,一个流代表了一个完整的请求-响应过程。帧是最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。多路复用,就是在一个 TCP 连接中可以存在多个流。

图片

从图中可见,所有的 HTTP/2.0 通信都在一个 TCP 连接上完成,这个连接可以承载任意数量的双向数据流。

每个数据流以消息的形式发送,而消息由一或多个帧组成。这些帧可以乱序发送,然后再根据每个帧头部的流标识符( stream id)重新组装。


首部压缩

HTTP1.1 不支持 header 数据的压缩,HTTP/2.0 使用 HPACK 算法对 header 的数据进行压缩,这样数据体积小了,在网络上传输就会更快。高效的压缩算法可以很大的压缩 header ,减少发送包的数量从而降低延迟。

缺陷

  • TCP 以及 TCP+TLS 建立连接的延时
  • TCP 的队头阻塞并没有彻底解决
  • 多路复用导致服务器压力上升
  • 多路复用容易 Timeout

多路复用导致服务器压力上升

多路复用没有限制同时请求数。请求的平均数量与往常相同,但实际会有许多请求的短暂爆发,导致瞬时 QPS 暴增。


多路复用容易 Timeout

大批量的请求同时发送,由于 HTTP2 连接内存在多个并行的流,而网络带宽和服务器资源有限,每个流的资源会被稀释,虽然它们开始时间相差更短,但却都可能超时。

即使是使用 Nginx 这样的负载均衡器,想正确进行节流也可能很棘手。其次,就算你向应用程序引入或调整排队机制,但一次能处理的连接也是有限的。如果对请求进行排队,还要注意在响应超时后丢弃请求,以避免浪费不必要的资源。


TCP 的队头阻塞并没有彻底解决

当 TCP 数据包在传输过程中丢失时,在服务器重新发送丢失的数据包之前,接收方无法确认传入的数据包。由于 TCP 在设计上不遵循 HTTP 之类的高级协议,因此单个丢失的数据包将阻塞所有进行中的 HTTP 请求的流,直到重新发送丢失的数据为止

HTTP3

HTTP3 背后的主要思想是放弃 TCP,转而使用基于 UDP 的 QUIC (快速UDP互联网连接)协议。

为了解决传输级别的线头阻塞问题,通过 QUIC 连接传输的数据被分为一些流。流是持久性 QUIC 连接中短暂、独立的“子连接”。每个流都处理自己的错误纠正和传递保证,但使用连接全局压缩和加密属性。每个客户端发起的 HTTP 请求都在单独的流上运行,因此丢失数据包不会影响其他流/请求的数据传输。

OAuth

http://www.ruanyifeng.com/blog/2019/04/oauth_design.html

简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者。……资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。

Protobuf

https://developers.google.com/protocol-buffers

Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data.

协议缓冲区是一种语言无关、平台无关的可扩展机制,用于序列化结构化数据。

Google最初开发了Protocol Buffers用于内部使用。Protocol Buffers的设计目标是简单和性能。特别地,它被设计地与XML相比更小且更快。

Protocol Buffers在Google内被广泛用来存储和交换各种类型的结构化数据。在Google,它被当作一个RPC系统的基础,并被用于几乎所有的跨服务器通信。

优缺点

https://www.cnblogs.com/niuben/p/14212711.html

优点:

  • 性能好/效率高
  • 有代码生成机制
  • 支持向后兼容和向前兼容
  • 支持多种编程语言

缺点:

  • 二进制格式导致可读性差
  • 缺乏自描述
  • 通用性差

npm 包

npm 包 protobufjs

protobuf.js is a pure JavaScript implementation with TypeScript support for node.js and the browser. It’s easy to use, blazingly fast and works out of the box with .proto files

protobuf.js是一个纯JavaScript实现,支持node.js和浏览器的TypeScript。它很容易使用,非常快,并且可以用。proto文件开箱即用


结合npm scripts

  "scripts": {
    "protojs": "pbjs -r apaas -t json-module -w commonjs -o src/protobuf/index.js  src/protobuf/messages/*.proto",
    "protots": "pbjs -t static-module src/protobuf/messages/*.proto | pbts -o src/protobuf/index.d.ts -",
    "proto": "run-s protojs protots"
  },

例子:report上报

// protobuf 编译出来的js
import {
  ApaasUserJoin,
} from '../protobuf';


export class ReportServiceV2  {
  protected Uint8ToBase64(u8Arr: Uint8Array): string {
    const CHUNK_SIZE = 0x8000; //arbitrary number
    let index = 0;
    const length = u8Arr.length;
    let result = '';
    let slice: any;
    while (index < length) {
      slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
      result += String.fromCharCode.apply(null, slice);
      index += CHUNK_SIZE;
    }
    return btoa(result);
  }
  protected buildUserJoinPaylod(payloadParams: ReportUserParams): string {
    let errMsg = ApaasUserJoin.verify(payloadParams);
    if (errMsg) throw Error(errMsg);
    let message = ApaasUserJoin.create(payloadParams);
    let buffer = ApaasUserJoin.encode(message).finish();
    return this.Uint8ToBase64(buffer);
  }
  protected buildBaseParams(id: number, src: string, payload: string): ReportParams {
    const qos = this.qos;
    const ts = Math.floor(new Date().getTime() / 1000);
    const sign = md5(`payload=${payload}&src=${src}&ts=${ts}`);
    return {
      id,
      src,
      payload,
      qos,
      ts,
      sign,
      requestId: this.reportUserParams.uid + new Date().valueOf(),
    };
  }
  protected buildUserJoinParams(
    src: string,
    payloadParams: ReportUserParams,
    lts: number,
    errorCode: number,
  ): ReportParams {
    const id = 9012;
    payloadParams.lts = lts;
    payloadParams.errorCode = errorCode;
    const payload = this.buildUserJoinPaylod(payloadParams);
    return this.buildBaseParams(id, src, payload);
  }
  async reportUserJoin(lts: number, errorCode: number) {
    const res = await this.fetch({
      path: `/v2/report`,
      method: 'POST',
      data: this.buildUserJoinParams('apaas', this.reportUserParams, lts, errorCode);,
    });
    return res.data;
  }

}

NAT

网络地址转换协议Network Address Translation (NAT) 用来给你的(私网)设备映射一个公网的 IP 地址的协议。一般情况下,路由器的 WAN 口有一个公网 IP,所有连接这个路由器 LAN 口的设备会分配一个私有网段的 IP 地址(例如 192.168.1.3)。私网设备的 IP 被映射成路由器的公网 IP 和唯一的端口,通过这种方式不需要为每一个私网设备分配不同的公网 IP,但是依然能被外网设备发现。

一些路由器严格地限定了部分私网设备的对外连接。这种情况下,即使 STUN 服务器识别了该私网设备的公网 IP 和端口的映射,依然无法和这个私网设备建立连接。这种情况下就需要转向 TURN 协议。

NAT穿透

NAT穿透是一种网络技术,用于在网络中通过网络地址转换(NAT)设备进行通信。NAT通常用于将私有IP地址转换为公共IP地址以实现多台计算机共享同一个公共IP地址。然而,NAT会对网络连接产生限制,特别是在p2p(点对点)或客户端与服务器之间直接通信的情况下。

NAT穿透技术允许在通过NAT设备的网络环境中建立直接的点对点连接,而无需中间服务器的转发。通过使用各种技术,如端口映射、UPnP(通用即插即用协议)和STUN(简单穿越UDP网络)等,NAT穿透技术可以帮助绕过NAT设备的限制,使得两个或多个设备能够直接通信。

NAT穿透可以提高网络连接速度、降低延迟,并允许在不同的设备之间共享文件、进行远程桌面访问、进行语音/视频通话等。它被广泛应用于p2p应用程序、在线游戏和实时通信应用程序中。

TURN

TURN是Traversal Using Relays around NAT的缩写,指的是一种用于在网络中穿越NAT的协议。NAT(Network Address Translation)是一种常见的网络技术,用于将内部网络的私有IP地址转换为外部网络的公共IP地址,从而实现多台设备共享一个公网IP地址。

然而,由于NAT的存在,导致在一些情况下,两台设备之间无法直接建立连接,需要通过一个中间节点进行转发。这就是TURN协议的作用,它提供了一种机制,使得位于不同NAT后面的设备能够建立起连接并进行通信,即使它们之间存在NAT或防火墙。

TURN协议的原理是在两台设备之间建立一个可信任的中继服务器,当设备A无法直接连接到设备B时,设备A将数据传输给中继服务器,中继服务器再将数据转发给设备B。这样,通过中继服务器的转发,设备A和设备B可以进行通信。

TURN协议主要用于实时通信应用中,比如语音通话、视频聊天等。它可以有效解决NAT穿越的问题,提供可靠的通信服务。

中继服务器

中继服务器是一种位于互联网中转传输数据的服务器。它位于数据传输的路径中,接收来自发送端的数据,并将其转发给接收端,起到传输数据的中转作用。中继服务器通常用于改善数据传输的稳定性和速度,尤其是在数据传输距离较远或网络状况较差的情况下。

缓存

Provisional headers are shown

https://www.jianshu.com/p/4cfa40121ecf

Request Headers 中发现存在 Provisional headers are shown 的警告

这个问题字面意思是“显示了临时报文头”,浏览器第一次发送这个请求,请求被阻塞,未收到响应。当要求浏览器再次发送这个请求时,上个同样的请求都还没有收到响应,浏览器就会报这个警告。

该数据直接采用了缓存,并没有发送请求

只从缓存中获得的通信显示为“显示临时标题”(或“执行”),因为该文件是从缓存中获取的,并且未进行通信,所以并不会显示详细标头。

如果上一个资源加载失败,可能导致从缓存加载的资源失败,即缓存资源请求之前的请求不能失败。强缓存from disk cache或者from memory cache,此时也不会显示。

其实都是与服务器没有进行或者完成正确的通信,所以只展示临时信息。

X-Cache Header

https://stackoverflow.com/questions/3027492/x-cache-header-explanation

CDN (Content Delivery Network) adds X-cache header to HTTP Response. X-cache:HIT means that your request was served by CDN, not origin servers. CDN is a special network designed to cache content, so that usr request served faster + to unload origin servers.

CDN(内容传递网络)将X-cache头添加到HTTP响应中。x -高速缓存:命中意味着你的请求是由CDN服务的,而不是源服务器。CDN是一种特殊的网络,旨在缓存内容,使usr请求服务更快+卸载源服务器。

Furthermore, there are a bunch of “X- “ headers provided by CDNs. They indicate HIT, MISS etc. You can simply install firebug plugin in firefox and request some progressive download video, probably it’ll be served by cdn node, so the HOST header in response might contain smth like cdn.rt.com and there will be “X- “ headers

此外,CDNs还提供了一堆“X-”头信息。它们表示命中、未命中等。你可以简单地在firefox中安装firebug插件并请求一些渐进的下载视频,可能它会被cdn节点服务,所以主机头响应可能包含smth像cdn.rt.com,将有“X-”头

X-Cache corresponds to the result, whether the proxy has served the result from cache (HIT for yes, and MISS for no)

X-Cache与结果相对应,无论代理是否已从缓存提供结果(HIT为是,MISS为否)

域名分片

https://developer.mozilla.org/zh-CN/docs/Glossary/Domain_sharding

由于浏览器限制了每个域(domain)的活动连接数。为了可以同时下载超过该限制数的资源,域名分片domain sharding)会将内容拆分到多个子域中。当使用多个域来处理多个资源时,浏览器能够同时下载更多资源,从而缩短了页面加载时间并改善了用户体验。

就性能而言,域名分片的问题在于每个域都需要额外的 DNS 查找成本以及建立每个 TCP 连接的开销。

由于 HTTP/2 没有限制并发请求(unlimited concurrent requests),因此启用 HTTP/2 后,就没必要再使用域名分片来解决并发限制了。

Request

mode

https://developer.mozilla.org/zh-CN/docs/Web/API/Request/mode

Request 接口的 mode 只读属性包含请求的模式(例如:corsno-corscors-with-forced-preflightsame-originnavigate 。)这用于确定跨域请求是否能得到有效的响应,以及响应的哪些属性是可读的。

  • same-origin — 如果使用此模式向另外一个源发送请求,显而易见,结果会是一个错误。你可以设置该模式以确保请求总是向当前的源发起的。
  • no-cors — 保证请求对应的 method 只有 HEADGETPOST 方法,并且请求的 headers 只能有简单请求头 (simple headers)。如果 ServiceWorker 劫持了此类请求,除了 simple header 之外,不能添加或修改其他 header。另外 JavaScript 不会读取 Response 的任何属性。这样将会确保 ServiceWorker 不会影响 Web 语义 (semantics of the Web),同时保证了在跨域时不会发生安全和隐私泄露的问题。
  • cors — 允许跨域请求,例如访问第三方供应商提供的各种 API。预期将会遵守 CORS protocol 。仅有有限部分的头部暴露在 Response ,但是 body 部分是可读的。
  • navigate — 表示这是一个浏览器的页面切换请求 (request)。navigate 请求仅在浏览器切换页面时创建,该请求应该返回 HTML。

Referer

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referer

Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

补充

CDN

CDN 的工作原理

内容分发网络(英语:Content Delivery Network,缩写:CDN)是指一种透过互联网互相连接的电脑网络系统,利用最靠近每位用户的服务器,更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户,来提供高性能、可扩展性及低成本的网络内容传递给用户。

使用 CDN 有什么好处

  1. 缩短网站加载时间 – 通过将内容分发到访问者附近的 CDN 服务器(以及其他优化措施),访问者体验到更快的页面加载时间。由于访问者更倾向于离开加载缓慢的网站,CDN 可以降低跳出率并增加人们在该网站上停留的时间。换句话说,网站速度越快,用户停留的时间越长。
  2. 减少带宽成本 – 网站托管的带宽消耗成本是网站的主要费用。通过缓存和其他优化,CDN 能够减少源服务器必须提供的数据量,从而降低网站所有者的托管成本。
  3. 增加内容可用性和冗余 – 大流量或硬件故障可能会扰乱正常的网站功能。由于 CDN 具有分布式特性,因此与许多源服务器相比,CDN 可以处理更多流量并更好地承受硬件故障。
  4. 改善网站安全性 – CDN 可以通过提供 DDoS 缓解、安全证书的改进以及其他优化措施来提高安全性。

CDN 边缘服务器

CDN边缘服务器是存在于网络逻辑极端或边缘的计算机。边缘服务器通常充当不同网络之间的连接。CDN 边缘服务器的主要目的是将内容存储在尽可能靠近发出请求的客户端计算机的位置,从而减少延迟并缩短页面加载时间。

边缘服务器是一种提供网络入口点的边缘设备。其他边缘设备包括路由器和路由交换机。边缘设备通常放置在Internet 交换点 (IxP)内,以允许不同的网络连接和共享传输。


源服务器是在网络资产未使用 CDN 时接收所有 Internet 流量的网络服务器。使用没有 CDN 的源服务器意味着每个 Internet 请求都必须返回到该源服务器的物理位置,无论它位于世界的哪个位置。这会增加加载时间,这会增加服务器与请求客户端计算机的距离。

CDN 边缘服务器将内容存储(缓存)在战略位置,以减轻一台或多台源服务器的负载。通过将图像、HTML 和 JavaScript 文件(以及可能的其他内容)等静态资产尽可能靠近请求的客户端计算机,边缘服务器缓存能够减少加载 Web 资源所需的时间。使用 CDN 时,源服务器仍然具有重要功能,因为重要的服务器端代码(例如用于身份验证的散列客户端凭据数据库)通常在源维护。

典型的 CDN 高速缓存过程包含以下 4 个步骤:

  1. 当用户请求网页时,用户的请求被路由到 CDN 中最近的边缘服务器
  2. 边缘服务器接着向源站服务器请求用户请求的内容。
  3. 源站响应边缘服务器的请求。
  4. 最后,边缘服务器响应客户端。

CDN 性能

CDN 与客户端的近距离价值是在向源站服务器发出初始请求之后体现出来的。一旦数据从源站服务器高速缓存到 CDN 网络中,来自客户端的每个后续请求都只需到达最近的边缘服务器即可。这意味着,如果最近的边缘服务器比源站服务器近,就能减少延迟,并且更快提供内容。

CDN回源

回源指您通过客户端请求访问资源时,如果CDN节点上未缓存该资源,或者您部署预热任务给CDN节点时,CDN节点会回源站获取资源。

  1. 当CDN节点没有缓存用户请求的内容时,会回源请求资源。
  2. 当CDN节点上缓存的内容已过期时,会回源请求资源。

CDN缓存多久更新

CDN节点的缓存内容不是实时更新的,只有当缓存内容到期后才能回源请求最新的内容并更新节点缓存。您可以通过设置缓存过期时间规则或者提交刷新请求来实现缓存内容的更新。

寻找边缘服务器

边缘服务器是分布在网络边缘、靠近终端用户的节点,它们位于传统的中心化云服务器之外,可以提供更接近用户的计算、存储、网络等服务。边缘服务器的主要作用是为终端用户提供更低延迟、更高带宽的服务。

对于CDN(内容分发网络)中的用户来说,寻找边缘服务器的过程通常是由CDN提供商自动处理的,以确保用户能够获得最佳的内容交付性能。

一般情况下,CDN提供商会使用一种称为“就近原则”的策略,即根据用户的物理位置,将其请求路由到最接近用户的边缘服务器上。这样可以减少数据传输的延迟和网络拥堵,提高内容交付的速度和质量。

当用户在浏览器中输入URL并发送请求时,CDN提供商会通过DNS解析将用户的请求转发到最近的边缘服务器。DNS解析会将域名解析为相应的IP地址,以确定用户的物理位置并将其请求路由到最佳的边缘服务器。

CDN提供商通常会在全球各地建立多个边缘服务器节点,这些节点分布在不同的地区和网络服务提供商中。通过这种全球分布的边缘服务器网络,CDN提供商可以将内容快速地交付给用户,提供更好的用户体验。

总而言之,CDN中的用户无需自行寻找边缘服务器,这个过程完全由CDN提供商自动处理。用户只需发送请求,CDN会根据用户的位置和网络状况选择最佳的边缘服务器来提供内容。

跨域

  1. 域名不同:当请求的域名或端口与当前页面的域名或端口不同的时候。
  2. 协议不同:当请求的协议与当前页面的协议不同的时候。
  3. 端口不同

crossOrigin

解决canvas图片getImageData,toDataURL跨域问题

crossOrigin是一个属性,可以设置在HTML中的img、video、audio等跨域元素上。

使用crossOrigin属性可以告诉浏览器在跨域请求时是否获取跨域的资源,以及如何处理获取到的跨域资源。

  1. 跨域资源共享:设置crossOrigin属性为”anonymous”或”use-credentials”,可以使浏览器在跨域请求时自动发送CORS(跨域资源共享)请求头,从而服务端可以决定是否允许跨域访问。
  2. 获取跨域图片的像素数据:如果设置crossOrigin属性为”anonymous”,那么在通过canvas的context.drawImage()方法绘制跨域图片时,可以获取到图片的像素数据。
  3. 防止跨域污染:设置crossOrigin属性为”anonymous”可以防止跨域污染,即不允许跨域资源修改当前页面的DOM结构和内容。
  4. 统计跨域资源加载失败:通过监听onerror事件,可以捕获跨域资源加载失败的情况,并进行统计或处理。

crossOrigin=anonymous相对于告诉对方服务器,你不需要带任何非匿名信息过来。例如cookie,因此,当前浏览器肯定是安全的。

options 请求

https://juejin.im/post/5edef7b2e51d45784213ca24?utm_source=gold_browser_extension

HTTP 的 OPTIONS 方法 用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为”*“)使用该方法。

简单来说,就是可以用 options 请求去嗅探某个请求在对应的服务器中都支持哪种请求方法。

在前端中我们一般不会主动发起这个请求, 是在跨域的情况下,浏览器发起”复杂请求”时主动发起的。

某些请求不会触发 CORS 预检请求,这样的请求一般称为”简单请求”,而会触发预检的请求则成为”复杂请求”。

跨域共享标准规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。

简单请求

  1. 请求方法只是以下几种:GET、HEAD、POST。
  2. HTTP头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Content-Type(只限于application/x-www-form-urlencoded、multipart/form-data、text/plain)。
  3. 请求中的任意XMLHttpRequestUpload 对象均没有被注册任何事件监听器。
  4. 请求中没有使用 FileReader对象。
  5. 请求中没有使用 FormData 对象。
  6. 请求中的任何部分,内容类型是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain。

复杂请求

  • 使用了下面任一 HTTP 方法,PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH
  • 人为设置了以下集合之外首部字段,即简单请求外的字段
  • Content-Type 的值不属于下列之一,即application/x-www-form-urlencoded、multipart/form-data、text/plain

options 关键的请求头字段

request header 的关键字段

关键字段 作用
Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法
Access-Control-Request-Headers 告知服务器,实际请求将携带的自定义请求首部字段

如:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

response header 的关键字段

关键字段 作用
Access-Control-Allow-Methods 表明服务器允许客户端使用什么方法发起请求
Access-Control-Allow-Origin 允许跨域请求的域名,如果要允许所有域名则设置为 *
Access-Control-Allow-Headers 将实际请求所携带的首部字段告诉服务器
Access-Control-Max-Age 指定了预检请求的结果能够被缓存多久

Options 请求优化

当我们发起跨域请求时,如果是简单请求,那么我们只会发出一次请求,但是如果是复杂请求则先发出 options 请求,用于确认目标资源是否支持跨域,然后浏览器会根据服务端响应的 header 自动处理剩余的请求,如果响应支持跨域,则继续发出正常请求,如果不支持,则在控制台显示错误。

由此可见,当触发预检时,跨域请求便会发送 2 次请求,既增加了请求数,也延迟了请求真正发起的时间,严重影响性能。

所以,我们可以优化 Options 请求,主要有 2 种方法。

  1. 转为简单请求,如用 JSONP 做跨域请求
  2. 对 options 请求进行缓存,服务器端设置 Access-Control-Max-Age 字段,那么当第一次请求该 URL 时会发出 OPTIONS 请求,浏览器会根据返回的 Access-Control-Max-Age 字段缓存该请求的 OPTIONS 预检请求的响应结果(具体缓存时间还取决于浏览器的支持的默认最大值,取两者最小值,一般为 10 分钟)。在缓存有效期内,该资源的请求(URL 和 header 字段都相同的情况下)不会再触发预检。(chrome 打开控制台可以看到,当服务器响应 Access-Control-Max-Age 时只有第一次请求会有预检,后面不会了。注意要开启缓存,去掉 disable cache 勾选。)

总结

options 请求就是预检请求,可用于检测服务器允许的 http 方法。当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起 OPTIONS 请求,即 CORS 预检请求,服务器若接受该跨域请求,浏览器才继续发起正式请求。

Vary

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Vary

Vary 是一个HTTP响应头部信息,它决定了对于未来的一个请求头,应该用一个缓存的回复(response)还是向源服务器请求一个新的回复 (和缓存有关系)

Vary出现在响应信息中的作用是什么呢?首先这是由服务器端添加,添加到响应头部。大部分情况下是用在客户端缓存机制或者是缓存服务器在做缓存操作的时候,会使用到Vary头,会读取响应头中的Vary的内容,进行一些缓存的判断。

Vary的字面意思是“不一、多样化”,顾名思义,它的存在区分同样的网络请求的不同之处,其实就是通过头部信息来区分。Vary存在于响应头中,它的内容来自于请求头中相关字段

缓存服务器会将某接口的首次请求结果缓存下来(包括响应头中的Vary),后面在发生相同请求的时候缓存服务器会拿着缓存的Vary来进行判断。比如Vary: Accept-Encoding,User-Agent,那么Accept-Encoding与User-Agent两个请求头的内容,就会作为判断是否返回缓存数据的依据,当缓存服务器中相同请求的缓存数据的编码格式、代理服务与当前请求的编码格式、代理服务一致,那就返回缓存数据,否则就会从服务器重新获取新的数据。当缓存服务器中已经缓存了该条请求,那么某次服务器端的响应头中如果Vary的值改变,则Vary会更新到该请求的缓存中去,下次请求会对比新的Vary内容。

官方解释Vary头:告知下游的代理服务器,应当如何对以后的请求协议头进行匹配,以决定是否可使用已缓存的响应内容而不是重新从原服务器请求新的内容。

Vary: * ,这个我不太理解,我个人的理解是,当Vary的值为“”时,意味着请求头中的那些字段的值不能用来区分当前请求是从缓存服务拿还是重新请求获取,在Android的OkHttp框架中,客户端接收到服务器的响应数据,进行缓存处理时,一旦判断响应头有Vary:时,就不缓存该条数据。所以我猜想缓存服务器会不会也是这样,当Vary的值为“*”时,不做缓存。

它被服务器用来表明在 content negotiation algorithm(内容协商算法)中选择一个资源代表的时候应该使用哪些头部信息(headers).

在响应状态码为 304 Not Modified 的响应中,也要设置 Vary 首部,而且要与相应的 200 OK 响应设置得一模一样。


条件型 CORS 响应下的缓存错乱问题

https://zhuanlan.zhihu.com/p/38972475

图片出现 不能跨域的缓存

在 @koa/cors 中

我们发现

    // Always set Vary header
    // https://github.com/rs/cors/issues/10
    ctx.vary('Origin');

这是为了解决条件型 CORS 响应下的缓存错乱问题

比如在同一个浏览器下,先打开了foo.taobao.com上的一个页面,访问了我们的资源,这个资源被浏览器缓存了下来,和资源内容一起缓存的还有Access-Control-Allow-Origin: https://foo.taobao.com响应头。这时又打开 bar.taobao.com上的一个页面,这个页面也要访问那个资源,这时它会读取本地缓存,读到的 Access-Control-Allow-Origin头是缓存下的 https://foo.taobao.com 而不是自己想要的 https://bar.taobao.com,这时就报跨域错误了,虽然它应该是能访问到这份资源的。

上面举的例子是“区分对待不同的Origin请求头”这类条件型 CORS 响应下引起的缓存错乱,这种问题是需要用户访问多个网站(foo.taobao.combar.taobao.com)后才可能触发的问题。“区分对待有无Origin请求头”也可能会造成类似的问题,而且在同一个站点下就有可能触发,比如用户先访问了foo.taobao.com的一个页面 A,页面 A 里用标签加载了一张图片,注意这时候这张图片已经被浏览器缓存了,并且缓存里没有 `Access-Control-Allow-Origin`响应头,因为发起的请求不带Origin请求头,此时用户又访问了foo.taobao.com的另一个页面 B,页面 B 里用 XHR 请求同一张图片,结果读了缓存,没有发现 CORS 响应头,报了跨域错误。在一些场景下,页面 A 和页面 B 有可能会是同一个页面,也就是说在同一个页面里就有可能触发这个问题。

使用 Vary: Origin 让同一个 URL 有多份缓存

有一个 HTTP 响应头叫Vary,vary 这个单词的意思是“变化”、“不同”的意思,Vary响应头就是让同一个 URL 根据某个请求头的不同而使用不同的缓存。比如常见的Vary: Accept-Encoding表示客户端要根据Accept-Encoding请求头的不同而使用不同的缓存,比如 gizp 的缓存一份,未压缩的缓存为另一份。

在 CORS 的场景下,我们需要使用Vary: Origin来保证不同网站发起的请求使用各自的缓存。比如从foo.taobao.com发起的请求缓存下的响应头是:

Access-Control-Allow-Origin: https://foo.taobao.com
Vary: Origin

bar.taobao.com在发起同 URL 的请求就不会使用这份缓存了,因为Origin请求头变了。还有标签发起的非 CORS 请求缓存下的响应头是:

Vary: Origin

在使用 XHR 发起的 CORS 请求也不会使用那份缓存,因为Origin请求头从无到有,也算是变了。

If CORS protocol requirements are more complicated than setting Access-Control-Allow-Origin to * or a static origin, Vary is to be used

翻译一下就是“如果你的 Access-Control-Allow-Origin响应头不是简单的写死成了*或者某一个特定的源(就是我总结的条件型 CORS 响应),那么你就应该加上Vary: Origin响应头。

withCredentials

https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/withCredentials

一个很重要的点: withCredentials永远不会影响到同源请求

XMLHttpRequest.withCredentials 属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。

在同一个站点下使用withCredentials属性是无效的。

此外,这个指示也会被用做响应中cookies 被忽视的标示。默认值是false。

如果在发送来自其他域的XMLHttpRequest请求之前,未设置withCredentials 为true,那么就不能为它自己的域设置cookie值。而通过设置withCredentials 为true获得的第三方cookies,将会依旧享受同源策略,因此不能被通过document.cookie或者从头部相应请求的脚本等访问。

不同域下的XmlHttpRequest 响应,不论其Access-Control-header 设置什么值,都无法为它自身站点设置cookie值,除非它在请求之前将withCredentials 设为true。

jwt相关

jwt可以用于验证用户身份信息,和传统的token作用差不多。

传统的token是服务端将用户信息进行MD5处理发送给客户端,客户端在请求时带上token验证。因为MD5是不可逆的,服务端需要去数据库查询相关用户信息,再进行一次MD5,用该MD5和客户端发来的MD5进行对比。

而jwt是不需要服务端经过数据库查询的操作,jwt有对应的加密解密算法,服务端拿到jwt后通过密钥解密可以把其中的用户信息拿到。

优势

无状态

由于 JWT 是自包含的,且无需在内存中保持请求之间的令牌,所以应用服务器可以做到完全无状态(stateless)。认证服务器可以颁发令牌,将其发回后就立即丢弃掉。

紧凑

JSON 比 XML 简介,所以当其被编码后,一个 JWT 比 SAML 令牌更小。这使得 JWT 成为一个在 HTML 和 HTTP 环境中传送的好选择。

更安全

oauth2.0

OAuth协议,是一种授权协议,不涉及具体的代码,只是表示一种约定的流程和规范。OAuth协议一般用于用户决定是否把自己在某个服务商上面的资源(比如:用户基本资料、照片、视频等)授权给第三方应用访问。此外,OAuth2.0协议是OAuth协议的升级版,现在已经逐渐成为单点登录(SSO)和用户授权的标准。

  • 第一,用户不再需要注册大量账号。在以前,我们每使用一个新的网站或者APP就需要注册一个账号,建立一套新的账户体系才能使用网站 / APP提供的服务。但是现在我们只需要拥有几个主流应用的账号,然后通过他们提供的第三方账号登录就可以使用一个新的网站/APP了(当然,我们也可以不使用腾讯百度等公司提供的授权服务,开发自己的授权服务端,这方面的内容我将放在下篇文章中介绍)。
  • 第二,用于单点登录。如果某个公司有很多个需要用户登录才能提供服务的子产品(比如:官网、M网站、APP、微信公众号、使用同一套账户体系的产品1、产品2等等),这种情况下为每个产品都开发一个登录、授权模块显然是不太优雅,因此比较好的解决方案就是所有需要登录的产品都请求同一个登录授权中心,进行统一登录授权处理。而OAuth2.0协议就可以实现符合上述要求的单点登录功能。
  • 第三,用于分布式系统的权限控制。因为基于OAuth2.0协议获得的令牌(Access Token)同时关联了接入的第三方应用、授权用户、权限范围等信息。因此,在第三方应用拿着Token请求资源的时候,资源服务应用就可以很容易根据其访问权限返回相应的数据。

使用授权码模式完成OAuth2.0授权的过程需要以下三个步骤:

  1. client请求授权服务端,获取Authorization Code
  2. client通过Authorization Code再次请求授权服务端,获取Access Token
  3. client通过服务端返回的Access Token获取用户的基本信息

content-type

网页链接

  • application/x-www-form-urlencoded:数据被编码为名称/值对。这是标准的编码格式。
  • multipart/form-data: 数据被编码为一条消息,页上的每个控件对应消息中的一个部分
  • text/plain: 数据以纯文本形式(text/json/xml/html)进行编码,其中不含任何控件或格式字符。postman软件里标的是RAW。
  • application/json

form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded

当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串追加到url后面,用?分割,加载这个新的url。

当action为post时候,浏览器把form数据封装到http body中,然后发送到server。 如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。 但是如果有type=file的话,就要用到multipart/form-data了。

当action为post且Content-Type类型是multipart/form-data,浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。

application/x-www-form-urlencoded方式是Jquery的Ajax请求默认方式

application/json,随着json规范的越来越流行,并且浏览器支持程度原来越好,许多开发人员易application/json作为请求content-type,告诉服务器请求的主题内容是json格式的字符串,服务器端会对json字符串进行解析,这种方式的好处就是前端人员不需要关心数据结构的复杂度,只要是标准的json格式就能提交成功,application/json数据格式越来越得到开发人员的青睐。

RTT

在计算机网络中,RTT指的是往返时延(Round-Trip Time),即从发送方发送数据到接收方再返回发送方所经历的时间。RTT可以用来衡量网络通信的延迟,从而判断网络的性能。

TTL

TTL (Time to Live) 表示在网络中数据包在传输过程中被允许存在的时间或跳数的最大值。每次数据包经过一个路由器或网络设备,其 TTL 值会减少一次。当 TTL 值减少到0时,该数据包将被丢弃或返回源 IP 地址。TTL 的主要目的是防止数据包在网络中无限循环,以保证数据包能够正常到达目标主机并在一定时间内传递完成。

CSP

http://www.ruanyifeng.com/blog/2016/09/csp.html

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP

内容安全策略 (CSP) 是一个附加的安全层,用于帮助检测和缓解某些类型的攻击,包括跨站脚本 (XSS) 和数据注入等攻击。

CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置。

CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。

两种方法可以启用 CSP。一种是通过 HTTP 头信息的Content-Security-Policy的字段。

Content-Security-Policy: script-src 'self'; object-src 'none';
style-src cdn.example.org third-party.org; child-src https:

另一种是通过网页的<meta>标签。

<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">

上面代码中,CSP 做了如下配置。

  • 脚本:只信任当前域名
  • <object>标签:不信任任何URL,即不加载任何资源
  • 样式表:只信任cdn.example.orgthird-party.org
  • 框架(frame):必须使用HTTPS协议加载
  • 其他资源:没有限制

Restful Api

网页链接

https://zhuanlan.zhihu.com/p/30396391?group_id=937244108725641216

REST是英文representational state transfer(表象性状态转变)或者表述性状态转移;Rest是web服务的一种架构风格;使用HTTP,URI,XML,JSON,HTML等广泛流行的标准和协议;轻量级,跨平台,跨语言的架构设计;它是一种设计风格,不是一种标准,是一种思想

Rest架构的主要原则

  • 网络上的所有事物都被抽象为资源
  • 每个资源都有一个唯一的资源标识符
  • 同一个资源具有多种表现形式(xml,json等)
  • 对资源的各种操作不会改变资源标识符
  • 所有的操作都是无状态的
  • 符合REST原则的架构方式即可称为RESTful

在Restful之前的操作:

http://127.0.0.1/user/query/1 GET  根据用户id查询用户数据
http://127.0.0.1/user/save POST 新增用户
http://127.0.0.1/user/update POST 修改用户信息
http://127.0.0.1/user/delete GET/POST 删除用户信息

RESTful用法:

http://127.0.0.1/user/1 GET  根据用户id查询用户数据
http://127.0.0.1/user  POST 新增用户
http://127.0.0.1/user  PUT 修改用户信息
http://127.0.0.1/user  DELETE 删除用户信息

防火墙

防火墙是一种网络安全设备或软件,用于保护计算机网络不受未经授权的访问、攻击或恶意软件的影响。它的主要作用如下:

  1. 访问控制:防火墙通过设置规则来控制网络通信的流量,例如,可以阻止未经授权的外部访问进入内部网络,限制特定IP地址或端口的访问等。
  2. 包过滤:防火墙可以分析传入和传出的网络数据包,并根据预先定义的规则来过滤或阻止恶意或可疑的数据包,以保护网络免受攻击。
  3. 网络地址转换(NAT):防火墙可以使用网络地址转换技术将内部网络的IP地址转换为外部网络能够识别的IP地址,以增加网络安全性并隐藏内部网络的真实IP地址。
  4. VPN支持:防火墙通常具备虚拟专用网络(Virtual Private Network, VPN)的功能,可以提供加密的远程访问方式,使远程用户可以安全地连接到内部网络。
  5. 日志记录和监控:防火墙可以记录网络活动的详细信息,包括连接尝试、访问日志等,从而帮助管理员监控网络的安全性,并用于后期的审计和分析。
  6. 病毒和恶意软件防护:防火墙可以集成防病毒和恶意软件功能,对传入的数据包进行实时扫描和检测,以阻止潜在的恶意软件感染。

总的来说,防火墙的作用就是通过设置权限和控制网络通信来保护网络安全,防范网络攻击和数据泄漏,提高网络的稳定性和可靠性。

CORB

https://juejin.cn/post/6844903831373889550#heading-12

Cross-Origin Read Blocking (CORB)

CORB 是一种判断是否要在跨站资源数据到达页面之前阻断其到达当前站点进程中的算法,降低了敏感数据暴露的风险。 (也就是无法收到正常的response 控制台会有warnning)

当跨域请求回来的数据 MIME type 同跨域标签应有的 MIME 类型不匹配时,浏览器会启动 CORB 保护数据不被泄漏,被保护的数据类型只有 html xmljson。很明显 <script><img> 等跨域标签应有的 MIME type 和 htmlxmljson 不一样。

CQRS

后端 CQRS 模式是一种架构模式,用于将系统的读操作(Query)和写操作(Command)分离。CQRS(Command Query Responsibility Segregation)模式的核心思想是根据系统的需求将读和写操作分离成不同的逻辑层,在设计和开发系统时,将可以处理读操作的层称为查询模型(Query Model),而可以处理写操作的层称为命令模型(Command Model)。

传统的 CRUD(Create, Read, Update, Delete)模式中,读操作和写操作共享数据模型和逻辑,这可能会导致一些问题。CQRS 模式通过将读和写操作分离,可以通过优化每个模型的设计和实现来提高系统的性能、可伸缩性和可维护性。

在 CQRS 模式中,读操作通常是对数据进行查询和展示的操作,可以通过专门的查询模型来处理。查询模型可以使用不同的数据存储和检索技术,例如使用缓存、索引、预计算等方法优化查询性能。查询模型还可以独立于写模型进行水平扩展,以应对高并发查询请求。

写操作通常是对数据进行修改和更新的操作,可以通过命令模型来处理。命令模型负责处理业务逻辑,校验输入数据,更新数据模型,并触发相应的事件或通知其他系统。通过分离命令模型和查询模型,可以使系统更加灵活、可维护和可扩展。

总结来说,CQRS 模式通过将系统的读和写操作分离,可以提高系统的性能、可伸缩性和可维护性。

同时,通过专注于不同的操作类型,可以使系统更加灵活、可定制和易于扩展。

在 nest 中:

https://docs.nestjs.cn/8/recipes?id=cqrs

隧道技术 tunnel

网络中的隧道技术是一种将网络流量封装在另一种网络协议中传输的技术。隧道技术通过在源和目标网络之间创建一个虚拟的通信隧道,将数据包封装在另一种协议的数据包中传输,然后在目标网络上解封并路由到目标位置。

隧道技术的常见用途包括:远程访问,实现远程办公或远程管理;跨越不同网络技术的连接,如将IPv6数据传输到IPv4网络;保障数据传输的安全性,如通过虚拟私有网络(VPN)隧道加密数据传输。

常见的隧道技术包括:点对点隧道协议(例如,点对点隧道协议(PPTP)、层二隧道协议(L2TP))、安全套接层(SSL) VPN、IP隧道(如,IPSec)等。

浏览器无法直接使用UDP

在浏览器中直接使用UDP协议发送数据是不可能的,因为浏览器通常只支持使用HTTP和HTTPS协议进行网络通信。UDP协议是无连接、不可靠的传输协议,它需要操作系统层面的支持,而浏览器通常不具备操作系统层面的权限和能力。

如果你需要在Web应用中使用UDP协议进行通信,可以考虑以下两种方式:

  1. 使用WebSocket:WebSocket是一种支持全双工通信的网络协议,可以在浏览器和服务器之间建立持久连接,并通过这个连接进行实时数据交互。WebSocket协议基于TCP协议,但可以在应用层使用UDP数据包进行通信。通过WebSocket,你可以在浏览器中使用UDP协议发送和接收数据。
  2. 使用服务器中转:在Web应用中,可以将UDP通信的功能放在一个独立的服务器上,并通过HTTP或其他协议在浏览器和服务器之间进行通信。浏览器将需要发送的数据通过HTTP请求发送到服务器上,服务器再将数据转发给UDP目标,同样道理,在UDP收到数据后,也通过服务器回传给浏览器。这种方式需要一个中转服务器来处理UDP通信和HTTP通信之间的转换。

测试网络质量

https://www.speedtest.net/

在线测试当前的网络质量