application-layer.md
HTTP
HTTP 是什么?
HTTP(HyperText Transfer Protocol) 是一种应用层、请求-响应式(客户端发请求,服务端回相应)、面向资源的协议,用于在客户端与服务端之间传输数据
它本身无连接、无状态(每个请求独立)(会话靠 Cookie/Token/Session 存在应用层),通过 URL/URI 标识资源,用方法(GET/POST/PUT/DELETE…)表达意图,用状态码表达结果,配合头部与缓存语义完成内容协商、压缩、鉴权、缓存等
协议在 HTTP 1.1 —— HTTP 2.0 —— HTTP 3.0(QUIC)演进中提升性能与可靠性,安全版是 HTTPS(HTTP over TLS)
HTTP 常见的状态码有哪些?
1xx:提示信息,是协议处理的一种中间状态,实际用到的比较少
2xx:服务器成功处理了请求
-
200 OK:常规成功
-
204 No Content:成功但无响应体(删除/幂等更新)
-
206 Partial Content:应用于 HTTP 分块下载或断点续传,表示相应返回的数据并不是资源的全部,而是其中的一部分
3xx:重定向,资源位置发生变动,需要重新发送请求
-
301 Moved Permanently:永久重定向
-
302 Found:临时重定向,资源还在,但暂时需要用另一个 url 访问
-
304 Not Modified:资源未修改,缓存重定向,重定向已存在的本地缓存文件
4xx:客户端错误
-
400 Bad Request:请求格式错误
-
401 Unauthorized:未认证,鉴权相关
-
403 Forbidden:已认证但无权限/被阻断
-
404 Not Found:资源不存在或未找到
5xx:服务端/网关内部错误
-
500 Internal Server Error:跟 400 有点像,是一个笼统通用的错误码
-
501 Not Implemented:方法未实现,请求的功能还未支持
-
502 Bad Gateway:网关或代理返回的错误码,表示服务器自身工作正常但在访问后端服务器时发生了错误
-
503 Service Unavailable:服务器当前很忙,暂时无法响应
HTTP 常见字段有哪些?
Host:发送请求时指定目标域名和端口号
User-Agent:指定客户端信息
Accept:指定可接受的响应内容类型
Cookie:传递客户端存储的 Cookie 数据,如 Session ID
Authorization:传递身份验证信息
Content-Length:服务器返回的数据长度
Connection:客户端要求服务器使用 HTTP 长连接
Content-Type:服务器返回的数据格式,指明消息主体的数据类型
Content-Encoding:服务器返回的数据使用的压缩格式
Referer:指定请求来源页面
Range:请求资源的部分内容,即断点传续
HTTP 请求报文和响应报文是怎样的?
HTTP 请求报文:
- 请求行:包含请求方法(GET、POST 等)、URL、HTTP 版本
- 请求头:包含客户端信息、请求内容类型、语言、Cookie 等
- 请求体:仅在某些请求方法(如 POST)中包含,包含实际的数据内容
HTTP 响应报文:
- 状态行:包含 HTTP 版本、状态码(如 200、404 等)、状态描述
- 响应头:包含服务器信息、缓存策略、内容类型等
- 响应体:包含返回的实际数据(如 HTML 页面、JSON 等)
GET 和 POST 有什么区别?
安全指的是方法不会破坏服务器上的资源,幂等是指多次执行相同的操作结果都是相同的
GET 是请求资源,重复执行不会改变资源状态,所以是幂等且安全的
POST 是提交数据,每次都会更改资源,所以是非幂等且不安全的
GET 直接把参数加在 url 之后,有长度限制,可以缓存,而 POST 是把参数放在请求体里,没有长度限制,默认不缓存
HTTP 请求方式有哪些?
常用的主要有 GET(1.0)、POST(1.0)、PUT(1.1) 和 DELETE(1.1)
GET 用于请求服务器资源,是幂等的;POST 用于向服务器提交数据,非幂等;PUT 是上传资源到服务器,用于更新或创建,因此它是幂等的;DELETE 就是删除资源
其他方式有 HEAD、TRACE、OPTIONS、CONNECT 和 PATCH
什么是强制缓存和协商缓存?它们的工作原理是什么?⭐
强制缓存:
是在本地的,包括 Expires(绝对时间)和 Cache-Control(相对时间)两个字段
Expires 是设置一个时间,当超时时标识缓存过期,需要重新向服务器发起请求,在时间范围内则使用缓存,缺点是本地时间不准确时判断也会不准确
Cache-Control 是通过 HTTP 响应头的 Cache-Control 字段实现,通过设置 max-age 来表示与上次请求的时间间隔,在时间间隔内则直接使用缓存
如果 HTTP 响应头部同时有这两个字段的话,Cache-Control 的优先级是比 Expires 要高的
协商缓存:
是在服务器的,在强制缓存失效时使用,通过 HTTP 的 ETag 或 Last-Modified 字段与服务器进行验证,判断资源是否被修改,主要是根据和服务端的协商结果来判断是否使用本地缓存
如果修改则状态码 200 返回新资源,并更新本地缓存,如果未修改则状态码 304,告诉浏览器要使用本地缓存
Last-Modified 是资源最近一次的修改时间,客户端读取到该字段时会在下一次请求的请求头中写 If-Modified-Since 字段,包括服务器第一次修改给的时间
服务器接收到 If-Modified-Since 的值后,会与 Last-Modified 比较,如果相同则说明资源没有修改,使用本地缓存,如果不同则返回新资源,更新本地缓存
这种方法的缺点是对比的是修改时间,并且记录的是秒级别的,如果文件名被修改了然后再改回来,文件是不变的,但时间变了,就会导致缓存失效,另外如果文件是被毫秒级修改的还会导致缓存不更新
ETag 则是根据文件指纹(文件 Hash 值比对),是由服务器根据文件内容计算得到的标识符,跟资源一起返回给客户端,客户端会在请求头字段的 If-None-Match 携带 ETag 值,服务器会进行比对,如果相同就使用本地缓存,不同就更新资源和 ETag 值
如果这两个字段同时都有的话,Etag 的优先级是更高的,但协商缓存中的两个字段都需要配合强制缓存中的 Cache-Control 字段来使用,只有未命中强制缓存时才能发起带有协商缓存字段的请求

HTTP 1.0 和 HTTP 1.1 的区别是什么?⭐
持久连接:
1.0 是短连接,每次请求都会重新建立 TCP 连接;1.1 引入了长连接,建立了一次 TCP 连接之后,只要通信双方没有一方主动断开连接,连接就不会断开,但如果长连接超过一定时间没有数据交互时服务端也会主动断开连接
管道化:
1.0 只能等前一个请求响应之后才能发送后续的请求;1.1 支持管道化,第一个请求发出后不用等响应即可继续发送后续的请求,但服务端只能按顺序返回响应
管道化解决了发出请求时队头阻塞的问题,但如果第一个响应的处理时间长,就会出现响应时队头阻塞的问题
请求头和响应头:
1.0 的请求头和响应头比较简洁;1.1 引入了一些新的字段,改进了对请求和响应的描述,比如 host 和 chche-control 等字段
错误处理、请求方法与身份认证:
1.0 的响应状态码和请求方法都比较少,仅支持基本的身份认证;1.1 增加了更多的响应状态码和更多的请求方法,如 PUT 和 DELETE,还引入了更多的身份认证机制,如 Authorization 和 WWW-Authenticate 头部
HTTP 2.0 与 HTTP 1.1 相比有哪些主要改进?⭐
二进制协议分帧:
1.1 使用文本格式传输数据;2.0 使用二进制格式传输数据,统称为头信息帧和数据帧,加快了数据传输效率
多路复用:
1.1 使用串行方式发送请求和响应;2.0 支持多路复用,引入了 Stream 的概念,多个 Stream 复用在同一条 TCP 连接上,允许在单个 TCP 连接上的不同 Stream 并行交错发送多个请求和响应,不同的 HTTP 请求用独一无二的 Stream ID 区分,接收端用该 ID 有序组装,从而解决了 1.1 中的响应队头阻塞问题
头部压缩:
1.1 支持 Body 压缩,Header 不支持压缩;2.0 引入了 HPACK 算法,可以对请求和响应的头部信息进行压缩,在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,后续只发送索引号而不是同样的字段,从而减少了冗余头部信息的传输
服务器推送:
1.1 需要客户端自己发送请求来获取相关资源;2.0 允许服务器主动推送资源给客户端,不需要客户端明确请求,减少了页面加载时间,并且客户端和服务器双方都可以建立 Stream
HTTP 3.0 有了解过吗?它与之前的版本有哪些主要不同?⭐
3.0 最大的特点是使用了 UDP 和 QUIC 协议,而不是像前几个版本那样使用 TCP
它解决了 2.0 没有解决的也就是 TCP 的队头阻塞问题,一个包的丢失会导致整个连接的多个请求都必须等待重传,另外 TCP + TLS 的连接握手过程也很慢,首次访问的延迟比较高
QUIC 连接上的多个 Stream 之间是相互独立的,当某个流发生丢包时只会阻塞那一个流,其他流不会受到影响,因此不存在队头阻塞问题,另外它的连接建立也是更快的,还实现了连接迁移,即使 IP 地址变化了,通过连接 ID 和上下文信息仍能很方便地复用原连接
HTTP 的 Keep-Alive 是什么?它在网络通信中有什么作用?
HTTP 的 Keep-Alive 是一种被称为 HTTP 长连接的应用层机制,它允许客户端和服务器在单个 TCP 连接上复用多个 HTTP 请求和响应,从而避免频繁建立和关闭连接的开销
什么是 HTTP 管道化?它在网络通信中有什么作用?
HTTP 的管道化是指客户端在接收到前一个请求的响应之前,就可以发送后续的多个请求,它主要用于提高网络通信效率,可以减少延迟、提高吞吐量并节省资源
什么是 HTTP 2.0 的服务器推送?它在网络通信中有什么作用?
服务器推送允许服务器主动向客户端推送资源,而不是仅在客户端请求时才发送,它可以在客户端发送请求之前就预先发送某些资源,从而减少延迟,提升页面的加载速度
RPC
RPC 是什么?
Remote Procedure Call,即 RPC,又叫做远程过程调用,它本身并不是一个具体的协议,而是一种调用的方式,它能让我们像调用一个本地函数方法一样去调用远端服务器暴露出来的方法,屏蔽掉了一些网络细节,从而让使用起来更加方便
大部分 RPC 协议使用的都是 TCP,但这并不是必须的,改用 UDP 或 HTTP 也同样可以实现类似的功能
为什么我们需要像 HTTP 和 RPC 这样的应用层协议,直接使用 TCP 不就可以了吗?⭐
TCP 的主要特点是面向连接、可靠、基于字节流,其中基于字节流指的是一个双向通道里流淌的二进制数据,也就是一大堆没有任何边界的 01 串,即所谓的粘包问题
所以我们需要在这个基础上加入一些自定义的规则用于区分消息边界,例如消息头消息体什么的,也就是所谓的协议,所以我们需要使用 HTTP 和 RPC
HTTP 和 RPC 有什么区别?
服务发现:
在 HTTP 中,知道服务的域名之后就可以通过 DNS 服务去解析得到它背后的 IP 地址
而在 RPC 中是由专门的中间服务去保存服务名和 IP 信息,比如 Consul 或 Etcd,甚至是 Redis,如果想访问某个服务就需要去这些中间件获得 IP 和 端口信息,DNS 也算其中的一种
底层连接形式:
在 HTTP 1.1 中默认建立底层 TCP 连接后会 Keep Alive,之后的请求和响应都会复用这个连接
RPC 跟 HTTP 的做法类似,也是通过建立 TCP 长连接进行数据交互,但还会再建一个连接池,在请求量大的时候会建立多条连接放在池中,要发数据时就在池里取一条连接,用完放回,下次再复用
但由于连接池有利于提升网络请求性能,所以许多编程语言的网络库都会给 HTTP 加个连接池,例如 Go 语言
传输的内容:
HTTP 1.1 是以字符串为主的,使用 Json 来序列化结构体数据
RPC 则使用体积更小的 Protobuf 或其他序列化协议去保存结构体数据,并且也不会像 HTTP 那样考虑各种浏览器的行为
既然有 HTTP 协议,为什么还要有 RPC?⭐
TCP 是七十年代出来的协议,HTTP 是九十年代才开始流行的,而 RPC 其实比 HTTP 还要早,它是八十年代出来的
RPC 最开始是用于客户端和服务器之间的建立连接和收发信息,使用自己的 RPC 协议就可以只连自己公司的服务器,但对于浏览器来说,它需要访问各种各样的服务器,所以需要一个统一的标准,从而诞生了 HTTP
现在其实浏览器和客户端之间已经没有那么泾渭分明了,很多软件既要支持网页版也要支持手机端和 PC 端,如果通信协议都使用 HTTP,那服务器也就只需要用这同一套就可以了,于是 RPC 后面就主要是用于公司内部集群中,比如各个微服务之间的通信
但在内部微服务中使用 RPC 而不是 HTTP 最主要的原因是二者传输的内容
HTTP 主要是 Json 来序列化结构体数据,这会导致其中的内容有大量冗余,比如我们如果约定好头部的第几位是 Content-Type,就不需要每次都把 “Content-Type” 这个字段都传过来,类似的情况在 Body 中也是同理
RPC 使用的则是体积更小的比如 Protobuf 或其他序列化协议去保存结构体数据,同时也不需要像 HTTP 那样考虑各种浏览器行为,比如 302 重定向跳转什么的,因此性能也会更好
但这里的 HTTP 指的是现在主流使用的 1.1,做了很多改进的 2.0 其实性能可能比很多 RPC 协议都要好,gRPC 的底层都是直接用的 HTTP 2.0,但由于出现得比较晚,也没有必要再替换了
可以说一下 gRPC 是一个什么样的协议吗?为什么会产生这样一个协议出来?⭐⭐
gRPC 是一个跨语言的高性能 RPC 框架,是 RPC 的具体实现,它默认使用 Protocol Buffers(Protobuf)进行接口定义与序列化
gRPC 基于 HTTP 2.0 作为传输层,天然支持流式多路复用、头部压缩、超时重试或取消、状态码和负载均衡等多种特性
它的产生主要是为了解决不同微服务之间通信的效率、契约与可观测性问题,它使用 .proto 来明确服务方法签名与消息结构,并集成了双向流、稳定的服务端推送等 HTTP 2.0 的多种优势,同时跨语言的特性也让它便于不同团队之间的协作
更深入一些的话,gRPC 是在同一 TCP 连接上多路复用多条流,在 HTTP 2.0 的尾部会返回 gRPC 状态和信息,客户端可以基于此做重试和故障分类,另外客户端也可以设置超时和取消,从而让服务端或中间件据此做资源回收
那 gRPC 相对于 RESTful 那种的接口设计有什么优势吗?⭐
性能方面:
gRPC 是使用 Protobuf 来二进制序列化,比 Json 更紧凑,解析更快,并且少传了许多冗余字段
它底层使用的就是 HTTP 2.0 的多路复用和头部压缩,支持同一 TCP 连接上并发多个请求和双向流式传输
强契约与自动化:
gRPC 通过 .proto 来明确定义服务与消息,并且可以自动生成多个不同语言的代码,REST 则经常靠文档或自定义,容易产生偏差或定义不一致、混乱问题
另外 Protobuf 在版本的演进和兼容机制方面也更可控和清晰,还有统一的错误模型、超时取消等功能,可以开箱即用
传输语义:
gRPC 中的状态码和元数据能清晰表达错误,便于自动重试,客户端也能显式传达时限,它也天然契合云原生,能很方便地集成服务发现和负载均衡相关的工具,更适合微服务间通信
RESTful 就是我们常说的 HTTP 1.1 吗?
RESTful 并不是 HTTP 1.1,它只是一种架构风格,并不绑定协议版本,只是很多 REST API 用的都是 HTTP 1.1,但它也可以跑在 2.0 或 3.0 上,同样 1.1 也可以承载非 REST 的风格
RESTful 是什么?它的状态问题有哪些?⭐
REST:Representational State Transfer,表述性状态转移,它是一个架构风格,RESTful API 一般是指在 HTTP 上尽量遵守 REST 这套设计原则的接口
REST 主张一切对外暴露的东西都抽象成资源,用 url 标识,比如 GET /users/123、POST /orders 等,资源本身不直接在网络上跑,而是它的表述在跑,比如 Json、HTML 之类的,客户端拿到资源的表述后再根据其中的内容决定下一步,这就是状态转移
REST 里常说的状态主要有资源状态、应用/会话状态和协议/连接状态三种,其中的无状态是指服务器不会在内存里保存客户端的会话上下文,每个请求必须自带完成操作所需的全部信息
例如登陆后用 token 或 JWT + 请求头来标识身份,而不是服务器用 Session 或上一个请求里服务端缓存的其他中间数据
RESTful 常见的状态问题主要有下面三个
状态码使用混乱:
比如无论成功回溯失败,HTTP 的状态码都是 200 OK,错误信息只在 JSON 里用字段表示,或者是状态码的语义混用、不一致,参数错、校验失败却返回 500,未登陆返回了 403 而不是 401,这些做法会导致客户端无法通过状态码区分具体的错误类型,告警或者中间件也没办法根据状态码做响应的处理
方法使用混乱:
用 GET 做会改动数据库的操作,或者是所有改动都用 POST,不区分场景,幂等性无法保证,从而导致在网络抖动重试时重复扣费或重复下单等错误
正确的做法是用 POST 和幂等键,或去重来避免重复,并定义清晰的资源模型与 url
缓存状态:
REST 是强调响应可缓存的,如果所有的接口都不设置缓存头,就会导致所有请求都打到后端,或者如果乱加 Cache-Control 导致客户端/中间层缓存了不该缓存的问题,导致状态陈旧、不一致
正常来说应该对只读和变化不频繁的资源设置缓存
你在用 gRPC 和其他的组件其他的服务做协调的时候,其中有可能会遇到有什么样的错误?或者你们在用 gRPC 来做组件的联调的时候会跟 RESTful 有什么不同吗,有没有相关的感受?⭐⭐⭐
场景一:网关或负载均衡组件不配合 HTTP 2.0,导致整条调用链不可用
比如我现在在 k8s 里有几个互相调用的 gRPC 服务,中间使用了 LB(Load Balancer)、Ingress 和 网关
Ingress 和 LB 是默认按照 HTTP 1.1 来处理的,或者可能它虽然支持,但只有在客户端传到负载均衡器的时候是 2.0,负载均衡器分发给后端时却降级成了 1.1,或者有些网关不支持 gRPC 的 Trailers 透传,只认普通的 HTTP body
这会导致如果调用 REST 接口完全没有任何问题,但 gRPC Client 就是会偶发失败,日志里 gRPC 层面也会是非 OK,因为错误是在 trailer 里的,中间转发丢失了
本质的原因还是 gRPC 的底层是基于 HTTP 2.0 的,它要求中间件支持 2.0 和能透传 Trailers,整个链路里的每一跳都必须是 2.0 并且 Trailers 没有丢失,也没有被升级或降级
而 RESTful 由于主要用的还是 1.1,对于中间件的要求很低,所以可用性比较高
解决方式的话可以在中间件中开启 2.0 的支持并且显式配置 gRPC upstream,用 grpc-health-check 来做健康检查,而不是只用纯 HTTP 的健康检查,还可以在本地用 grpcurl 从外面打到服务,看响应的 grpc-status 和 Trailers 是否完整
场景二:超时传递不当,导致整条链路随机超时
gRPC 的超时是通过 context 的 deadline 从入口一路到底自动传递的,如果上游给的上下文中超时时间不够,下游还会继续把这个快过期的上下文继续传给它的下游
这就导致一旦流量上来,队列稍微变长了一些,某个环节比平时可能稍微慢了一点点,那整条链路就会出现,上游判断超时,下游其实已经算完了,但在发回结果时由于上下文已经过期所以被上游丢弃,造成 CPU 和内存都很正常,服务也没挂,但一到高峰期就报非常多超时的现象
调试的时候会发现比如服务 A 给服务 B 留了 200ms,服务 B 又给服务 C 减去一些,然后服务 C 里还有比如 DB 或者 Redis 调用什么的,导致最后链路上真正留给业务逻辑的时间几乎没多少
在设计时就要统一约定好一条调用链的整体耗时,再按照比例拆分给每一层,不要默认在每一层都直接重置超时,而是合理缩减,并且服务内部在看到超时错误字段时要快速返回,而不是继续做无意义的逻辑
在 RESTful 中超时更多是每层独立的,不同服务和网关的超时设置可能都不同,也不会自动传递,当然,也不会像 gRPC 那样逻辑更干净
场景三:联调排障时的可视化
当我写好了一个 gRPC 服务和一个 RESTful 服务时,前端或者写其他服务的同事询问我该如何调我的接口
如果是 RESTful,用 curl 或 API 文档工具,由于使用的是 Json,可视化是非常直观的,哪怕写错了字段也能肉眼看出来,nginx 日志也能直接看到 body 具体内容
如果是 gRPC,首先对方得有一份 .proto 文件,或者是使用其他专门的工具比如 grpcurl,并且看到的是二进制的内容,错误码是在 Trailers 里的
直接带来的差异是如果是想临时试一下的话,RESTful 会非常方便,浏览器 F12 或者是各种工具都可以直接用,只要 API 文档过得去就能直接联调
而 gRPC 更适合已经有 proto 和生成代码的团队,因为一切都是按照自动生成的 client stub 来的,类型安全,字段也错不了,联调反而会更顺利
最好的做法是对内统一用 gRPC + protobuf,所有服务间通信都走 stub,对外或联调时加一个 grpc-gateway,自动把部分接口暴露成 REST + Json,这样前端和测试只要会调 HTTP 就行,或者就是在测试环境开一个 grpcui,直接在浏览器调用
WebSocket
什么是 WebSocket?它在网络通信中有什么作用?
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它允许客户端和服务器之间建立持久的连接
它在网络通信中实现了实时的数据交换,被广泛用于需要低延迟和双向通信的应用场景,如在线游戏、实时聊天等
既然有 HTTP 协议,为什么还要有 WebSocket?⭐
一个 TCP 连接的两端在同一时间里,双方都可以主动向对方发送数据,即全双工,而现在使用最广泛的 HTTP 1.1 虽然也是基于 TCP 协议的,但同一时间里客户端和服务器只有一方能主动发数据,也就是半双工
在用户无感知的情况下服务器能将数据主动推送给客户端的解决方案,也就是服务器推送技术,主要有不断轮询和长轮询两种
不断轮询指的是前端不断定时发 HTTP 请求给服务器,而长轮询则是将请求超时时间设置得很大,只要在超时时间内服务器收到了请求就立马返回结果给客户端,如果超时就马上发现下一次请求,在消息队列中这种长轮询机制在消费者去取数据时也是很常见的
但这两种方案都不是服务器主动发送的数据,只能解决比如扫码登录这样的简单场景,但如果是游戏就会有大量数据需要服务器主动推送
所以就需要一个支持客户端和服务器之间能互相主动发送大量数据的场景的基于 TCP 的新协议,于是就有了 WebSocket
WebSocket 连接是怎么建立的?⭐
为了兼容不同的使用场景,WebSocket 连接是通过 HTTP 协议升级而来的,如果想建立 WebSocket 连接,就会在 HTTP 请求里带上一些特殊 header 字段
比如升级协议(Connection:Upgrade),并且升级成 WebSocket 协议(Upgrade:WebSocket),还会带上一段随机生成的 base64 码(Sec-WebSocket-Key)发给服务器
如果服务器支持升级,就会走 WebSocket 握手流程,根据客户端生成的 base64 码,用某个公开的算法变成另一段字符串,放在 HTTP 响应的 Sec-WebSocket-Accept 字段里,并带上 101 Switching Protocols 状态码返回给服务器
然后浏览器会用同样的公开算法把 base64 码转成另一段字符串,如果这段字符串跟服务器传回来的一致,那验证通过,也就是经过了一来一回两次 HTTP 握手,成功建立了 WebSocket 连接
WebSocket 只有在建立连接时才用到了 HTTP,它并不是基于 HTTP 的新协议,在升级完成之后就跟 HTTP 没有任何关系了
其他
DNS 查询过程是怎样的?它是如何实现域名解析的?
DNS 查询分为迭代查询和递归查询
迭代查询:
查看本地是否缓存域名的 IP 地址 —— 查询本地 DNS 服务器 —— 查询根 DNS 服务器 —— 根 DNS 服务器告知本地 DNS 服务器该查询哪个顶级 DNS 服务器 —— 本地 DNS 服务器向顶级 DNS 服务器发送查询请求 —— 顶级 DNS 服务器告知本地 DNS 该查询哪个权限 DNS 服务器 —— 本地 DNS 查询根 DNS 服务器 —— 获取域名 IP 地址并更新缓存
递归查询:
跟迭代查询是类似的,不同之处在于迭代查询是由本地 DNS 服务器依次询问根、顶级和权限 DNS 服务器,而递归查询是由根去查询顶级,顶级再查权限,获得结果再依次返回
Cookie 和 Session 是什么?它们在网络通信中扮演什么角色?有什么区别?⭐
Cookie 和 Session 都是用来管理用户状态和身份的工具
Cookie:
存储在用户浏览器中的小型文本文件,用于在用户和服务器之间传递数据,通常服务器会将一个或多个 Cookie 发送到浏览器,浏览器会将这些 Cookie 存在本地
服务器在接收到来自客户端的请求后,会分析存放在请求头中的 Cookie 得到客户端特有的信息,从而动态生成相应的内容
Session:
用于维护用户登录状态和用户临时数据,在客户端访问服务器时,服务器会把客户端信息以 Session 记录在服务器上,并为每个用户分配一个唯一的 Session ID,这个 ID 通常存储在 Cookie 中
区别:
Cookie 存储在浏览器中,存储容量相对较小,也很容易被读取和篡改,可以设置过期时间,在每次 HTTP 请求中都会被自动发送到服务器
Session 存储在服务器上,存储容量一般取决于服务器的配置和资源,不太容易被读取和篡改,它依赖会话的持续时间或用户活动,ID 通常通过 Cookie 或 url 参数传递
序列化和反序列化是什么?
基于 TCP 传输的消息无非都是 Header 和 Body,Header 用于标记一些特殊信息,其中最重要的是消息体长度
Body 则是放真正需要传输的内容,如果是字符串或者数字都没什么问题,可以通过编码或直接转为二进制,但结构体也需要变成二进制,这便是序列化,也就是将结构体转为二进制数组的过程
反序列化就是反过来将二进制数组复原成结构体的过程
常用的方案有 Json 和 Protobuf 等
HTTPS(待整理)
HTTP 与 HTTPS 有哪些区别?
HTTPS 解决了 HTTP 的哪些问题?
HTTPS 是如何建立连接的?其间交互了什么?
HTTPS 的应用数据是如何保证完整性的?
HTTPS 一定安全可靠吗?
HTTPS RSA 的握手过程是什么?
HTTPS ECDHE 的握手过程是什么?
HTTPS 如何优化?
既然有 HTTP 协议,为什么还要有 RPC 和 WebSocket 协议?
HTTPS 为什么安全?
A:HTTPS 通过 TLS 实现加密、完整性校验和身份认证,支持前向安全,它在握手阶段以服务器证书公钥完成非对称密钥交换,协商会话密钥,随后的业务报文用对称算法加密并附带 MAC 校验,浏览器会对证书链和域名做验证
一个数字证书上面一般都会有什么内容?
A:证书通常含版本、序列号、签名算法、颁发者 Issuer、主体域名/组织、有效期、公钥信息、指纹摘要及扩展、颁发者数字签名等,客户端会验证签名并校验证书链与有效期
介绍一下 HTTPS
A:HTTPS 是在 HTTP 的基础上加入了 TLS 或者说 SSL 加密的通信协议,默认走 TCP 443 端口,它的核心在于握手阶段,客户端发 ClientHello,服务器选定加密套件并返回证书,客户端验证证书合法后,用非对称加密协商出对称密钥,最后双方互发 Finished 消息确认;握手完成后,所有数据都通过对称加密和消息认证码进行保护,并用 ECDHD 提供前向安全,保证机密性、完整性和服务器身份认证;相比 HTTP 的明文传输,虽然 HTTPS 增加了握手开销,但一次握手后就能复用会话,还支持 http 2 的多路复用
为什么要同时使用公钥和私钥,这两个密钥有什么用
A:公钥和私钥一对是非对称加密的基础,用对方的公钥加密能确保只有拥有对应私钥的那一端才能解密查看,用自己的私钥对数据签名,让对方通过我的公钥来验证,保证消息确实来自我并且没有被篡改,在 HTTPS 中,服务器把公钥打包在 CA 签发的证书里,客户端验证证书无误后,用该公钥校验服务器私钥对握手数据的签名,再用公钥加密,只有服务器私钥能解开,这样既验证了服务器身份,也保证了后续通信的机密性和完整性