http HTTP面试题 - HTTP2 面试题
引言
依据网络上的常见面试题进行收集,根本能应酬大部分的场景,HTTP大部分是八股,所以间接开始背书即可。
关联文章
关联:HTTP - HTTP2 知识点
根底问题
为什么要批改 HTTP?
HTTP 1.X 自呈现以来便统治整个互联网15年以上,然而它的历史包袱也慢慢变大,高效加载资源的需要日趋显著,解决队头阻塞、头部臃肿等问题也逐步被摆上台面。
HTTP1.X 的版本遗留了两个比较严重的问题:
- 连贯过多导致TCP梗塞的管制变得有效化,网络拥塞造成不必要的带宽占用。
- 浏览器因为梗塞占用本不属于它的资源,同时会呈现大量“反复”申请的资源数据。
业界已经呈现了大量计划尝试解决这些问题,比方:
- spriting 图片合并
- data: inlining 内联数据
- Domain Sharding 域名分片
- Concatenation 文件合并
然而无论如何优化,HTTP1.X 协定自身造成的网络拥塞是无奈防止的,作为极客公司的Google为了推动本人的产品和业务须要更加高速的WEB互联网环境,推动HTTP的改革势在必行,Google自身也有足够的用户量和技术实力推动。
推动HTTP/2
IETF的HTTP工作组是HTTP/2的理论推动者,这个工作组保护了HTTP协定,而组织的成员由HTTP实现者、用户、网络运营商以及HTTP专家等组成。
除开IETF这个非盈利的神奇组织之外,还有各大支流浏览器的一些专家比方Firefox,Chrome,Twitter,Microsoft 的 HTTP stack,Curl 和 Akamai 等“大型”我的项目的工程师,以及诸如 Python、Ruby 和 NodeJS 之类的 HTTP 实现者。
留神HTTP协定是通过“邮件”沟通探讨进行欠缺和制订的,所有的探讨尽管构建在W3C的邮件服务商上,然而W3C自身对于HTTP推动没多大的帮忙。
咱们能够这么了解,IETF 是协定的真正推进者,也是协定规范的发布者,然而具体的协定制订可能来自各种团队和组织或者能够是集体,协定制订的日常工作是在邮件进行细节探讨,当然邮件探讨不能是聊闲话,每次邮件探讨只有存在产出的才算是合格,于是HTTP2协定就这样一步步欠缺并且最终实现。
服务器怎么样晓得客户端须要 HTTP2 连贯?
HTTP2和HTTP的申请协定都是http结尾,普通用户个别是不晓得客户端是否反对HTTP的(或者连HTTP是啥都不晓得),那么客户端是如何在地址都是以Http结尾的状况下辨认申请是一个HTTP2的连贯的呢?
这个知识点考查的是 连贯前言,这个前言是 设计如此,无需过多纠结。
“连贯前言”是规范的 HTTP/1 申请报文,应用纯文本的 ASCII 码格局,申请办法是特地注册的一个关键字“PRI”,全文只有 24 个字节。
In HTTP/2, each endpoint is required to send a connection preface as a final confirmation of the protocol in use and to establish the initial settings for the HTTP/2 connection. The client and server each send a different connection preface. The client connection preface starts with a sequence of 24 octets, which in hex notation is: 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a That is, the connection preface starts with the string "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"). This sequence MUST be followed by a SETTINGS frame ([Section 6.5](https://datatracker.ietf.org/doc/html/rfc7540#section-6.5)), which MAY be empty. The client sends the client connection preface immediately upon receipt of a 101 (Switching Protocols) response (indicating a successful upgrade) or as the first application data octets of a TLS connection. If starting an HTTP/2 connection with prior knowledge of server support for the protocol, the client connection preface is sent upon connection establishment.
下面一大段话其实都是围绕 PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n这一串作为外围,依据HTTP定义规定如果客户端发送了这一串字符,并且通过 SETTINGS 帧告知服务端本人冀望HTTPS2 连贯,服务端就晓得客户端须要的是TLS的HTTP2连贯。
在 Wireshark 里,HTTP/2 的“连贯前言”被称为“Magic”,意思就是“不可知的魔法”。
为什么叫HTTP2不叫HTTP2.0?
一句话就是就是为了规范化和打消歧义。工作组为了避免HTTP 1,HTTP1.1 这样的容易误会的协定名称做的改良,从HTTP2开始,所有的降级不会呈现小版本升级,只有存在微小更新,才会呈现大版本的改变。
为什么要退出头部压缩?
具体能够看Patrick McManus对于头部压缩的性能晋升的探讨:# In Defense of Header Compresson
咱们间接从数据能够看到压缩过后的音讯比没有压缩的要快出好几倍。
Test 50ms 100ms 200ms 300ms1 52 102 202 302 2 52 102 202 3023 358 808 1401 21084 256 506 1006 1542Test 1 is with the cookie and zlib compressionTest 2 is without the cookie but with zlibTest 3 is with the cookie and no zlibTest 3 is without cookie and no zlib
HTTP/2 与 SPDY的关系
SPDY是谷歌为了凑合HTTP1.X 的性能和网络阻塞问题的试验“玩具”,它用上亿的用户量兜底一步步改良SPDY的协定,这项技术起初也受到了Mozilla和Nginx等实现者的关注,SPDY起初因势利导成为了HTTP2的重要改良点。
后续IETF工作组通过探讨最终采纳了 SPDY/2 作为HTTP2的根底,在IETF制订HTTP2的过程中,SPDY/2的外围开发团队都有全程参加,在后续Goole看到SPDY曾经被HTTP2齐全包容了,于是在2015年间接删除了SPDY2,全面面向应用HTTP2。
HTTP/2 和 HTTP/1.x 的次要区别是什么?
在高版本的 HTTP/2 次要区别如下:
- 是二进制的,而不是文本的。
- 多路复用,实现应用层无队头阻塞。
- 一个连贯能够进行并行处理。
- 应用HPACK算法压缩头部来缩小开销。
- 容许服务器被动将响应"推送"到客户端缓存中。
- 申请容许进行服务端推送,双向并发传输。
为什么抉择 HPACK?
第一个起因,SPDY2 倡议无论申请还是回传响应数据方都应用独自的GZIP算法进行头部压缩(发现效率晋升非常明显)。然而从那时起,一个"重要"的攻击方式 CRIME 诞生了,这种形式能够攻打加密文件外部的所应用的压缩流。
同样的,TLS压缩中也存在CRIME攻打的伎俩,黑客利用CRIME能够对于压缩TLS加密报文进行探测,并且能够解密复原窃取密钥等信息,同时能够利用JS截取对TLS加密的HTTP传输数据,获取其中的Cookie信息和令牌窃取用户信息成为。
HPACK就是在在 GZIP 的安全性生效额根底上呈现的,SPDY设计了HPACK算法增强Header压缩的安全性。
顺带一提,TLS 1.3 禁止压缩加密报文传输并且间接废除压缩加密传输。
HTTP2 必须加密么?
尽管RFC文档没有明确要求HTTP2须要TLS加密,然而要晓得支流浏览器大多都不反对不加密的HTTP2,所以HTTP2是实践上的自由选择加密,实际上的“加密连贯”。
HTTP/2 能够扩大新字段吗?
HTTP/2 尽管在语法上做了很多扭转,然而根本的报文构造是没有变的,如果传输新的字段或者传输新的类型,那么HTTP的前后兼容就会非常麻烦,这也是HTTP2没有在结构上做根本性扭转的起因。
为了让使用者能够从HTTP1过渡到HTTP2,HTTP做了许多暗藏操作,比方连贯前言,遵循HTTP协定申请头。
现实情况是HTTP2呈现之后至今这么多年,本应该是8、90% 的普及率,理论只有50%的网站应用,能够看到一个降级协定除非足够像是TLS1.2那样足够吸引人,否则推广起来并不是容易的事件。
此外踊跃推动HTTP2倒退的缔造者谷歌自身在宣传高低的功夫并不是很多。
HTTP2的安全性如何?
HTTP2的自身安全性并不靠谱。具体细节能够看:https://www.rfc-editor.org/rfc/rfc8164,在这外面简略形容了一些根本的平安攻打隐患,比方常见的降级攻打,HTTP2会把对应的响应字段删除,再比方服务器管制中应用“Alt-Svc”标头字段形容整个源的策略,服务器不应该容许用户内容设置或批改此标头的值等等。
此外厂商推广HTTP2 “要求”和TLS绑定上线的的另一个起因是TLS在过后的很多加密套件和加密办法能力在破绽,椭圆曲线函数逐步风行并且日渐成为网络安全传输的必需品,集体看来HTTP2的TLS绑定侧面反映了椭圆函数曲线加密的推广需要。
怎么晓得浏览器是否反对HTTP2?
下图只列举一些支流浏览器,能够查看上面这一个网站:https://caniuse.com/http2,HTTP 2 曾经颁布很多年了,所以近几年的支流浏览器根本都反对HTTP2。
HTTP/2 会取代 HTTP/1.x 吗?
答案是不会,至多从HTTP2颁布了近8年之后仍然只有50%的网站反对HTTP2,从这一份数据就能够看出HTTP2的普及率尽管不错然而远没有设想中可观,集体认为更多人在期待HTTP3的遍及。
不会齐全取代的根本原因是不同的代理服务器以及我的项目部署的形式不同,不能强制让所有的服务器降级,HTTP1.X 仍然会有很长的运行工夫。
HTTP2 还有哪些缺点?
HTTPS3 改良的都是HTTP2的缺点,次要的问题如下:
1、没有解决TCP队头阻塞问题,导致如果有丢包申请会期待重传,阻塞前面的数据,有可能不如HTTP1.1的多个TCP连贯 TCP 以及 TCP+TLS 建设连贯的延时。
2、多路复用导致服务器压力回升,没有限度同时申请数。申请的均匀数量与通常状况下雷同,但很多服务器业务往往会有许多申请的短暂暴发导致刹时 QPS 暴增。
3、HTTP2的多路复用容易产生大批量的申请Timeout,因为连贯时内存在多个并行的流,而网络带宽和服务器资源无限,每个流的资源会被浓缩,也就是说外表上看上去是十分靠近的工夫理论发送可能超时。
能比照一下 HTTP/2 与 HTTP/1、HTTPS 的相同点和不同点吗?
相同点:
- 上层都是都是基于TCP协定,HTTP/2尽管没有规定必须加密,然而浏览器会进行要求加密HTTP2,所以咱们看到的大部分HTTP2实现服务网站都是加密连贯的。
- 基于申请-响应模型,schema还是http或https不会有http2。
不同点:h2应用二进制传输音讯并且通过HPACK压缩申请头实现流多路复用,服务器推送等。
应用h2和h2c划分加密和非加密申请有什么区别?
h2应用二进制传输音讯并且通过HPACK压缩申请头实现流多路复用,服务器推送等。h2c长处是性能,不须要TLS握手以及加解密。能够通过curl工具结构h2c申请;
应该怎么了解 HTTP/2 里的“流”?
h2的流咱们能够看作是理论存在的,因为它是应用帧传输数据的,雷同 StreamId 的帧组成了音讯以及流;通过类比相似于咱们把一个积木玩具依照肯定的规定拆分为不同的整机,整机能够一起发送过去,组装人员只须要晓得组装程序即可还原。也能够能够应用HTTP1的Chunked 的思路了解。
动静表保护、流状态转换很简单,你认为 HTTP/2 还是“无状态”的吗?
集体认为HTTP2是存在状态这个概念的。对下层利用来说,Headers头部压缩当中动静表保护、流状态转换这些操作对它不可见,利用的实现方也不须要为了实现HTTP2传输进行手动的状态保护。头部压缩角度来看能够认为是“无状态”的。
HTTP2引入的帧状态是帧的进一步体现,具体能够看上面的流状态流转图。
+--------+ send PP | | recv PP ,--------| idle |--------. / | | \ v +--------+ v +----------+ | +----------+ | | | send H / | | ,------| reserved | | recv H | reserved |------. | | (local) | | | (remote) | | | +----------+ v +----------+ | | | +--------+ | | | | recv ES | | send ES | | | send H | ,-------| open |-------. | recv H | | | / | | \ | | | v v +--------+ v v | | +----------+ | +----------+ | | | half | | | half | | | | closed | | send R / | closed | | | | (remote) | | recv R | (local) | | | +----------+ | +----------+ | | | | | | | | send ES / | recv ES / | | | | send R / v send R / | | | | recv R +--------+ recv R | | | send R / `----------->| |<-----------' send R / | | recv R | closed | recv R | `----------------------->| |<----------------------' +--------+ send: endpoint sends this frame recv: endpoint receives this frame H: HEADERS frame (with implied CONTINUATIONs) PP: PUSH_PROMISE frame (with implied CONTINUATIONs) ES: END_STREAM flag R: RST_STREAM frame
HTTP/2 的帧最大能够达到 16M,你感觉大帧好还是小帧好?
仁者见仁智者见智,认为大帧好的会感觉小帧须要很多额定的头信息有数据冗余。 而认为小帧比拟好则感觉小帧合乎大部分常见的业务,当然如果在某些特定场景里比方下载大文件能够适当加大。
HTTP2头字段有什么非凡规定?
这个问题集体有些感触,过来集体碰到过CONTENT-TYP
、Content-Type
、 content-type
这样的申请头部,因为HTTP1.X对于头字段写法很随便,HTTP2 为了避开这些问题所有设置所有的头字段必须小写。具体看上面的RFC文档形容:
Just as in HTTP/1.x, header field names are strings of ASCII characters that are compared in a case-insensitive fashion. However, header field names MUST be converted to lowercase prior to their encoding in HTTP/2就像在 HTTP/1.x 中一样,标头字段名称是 ASCII 字符串 以不辨别大小写的形式比拟的字符。 然而, 标头字段名称必须在其之前转换为小写 HTTP/2 中的编码
随着 http2 的倒退,前端性能优化中的哪些传统计划能够被代替
- 雪碧图
- 资源文件合并
- 域名发散
- 资源内联
http2 中 Stream 与 Frame 是什么关系?
- Stream 为 Request/Response 报文的双向通道,一个残缺资源的申请与相应是一个 stream,非凡的 stream 作为 Settings、Window_Update 等 Frame 发送的通道
- Frame 为 http2 通信的最小单位,有 Data、Headers 等,一个 Stream 蕴含多个 Frame,如一条 http 申请蕴含 Header、Data Frame 等
实现细节问题
Http2 中 Server Push 与 WebSocket 有什么区别?
- HTTP2 Server Push,个别用于服务器解析
index.html
同时推送JPG/JS/CSS
等资源,而防止了服务器发送屡次申请。 - websocket,用于服务器与客户端手动编写代码去推送进行数据通信。
谈谈 HTTP/2 如何解决“队头阻塞”问题
先说一下论断:HTTP2 解决了应用层的的队头阻塞,但没有解决TCP队头阻塞问题,咱们能够认为HTTP2的队头阻塞很像是把管道化的概念实现的更好。
首先是HTTP1.X的队头阻塞问题,HTTP1在浏览器中的同一域名的并发连接数无限,如果连接数超过下限,排在前面的连贯就须要期待后面的资源加载实现,有时候呈现的浏览器空白并且始终“转圈”也是如此。
各大服务网站的解决形式是应用资源宰割的形式,配合多域名和主机进行多个IP避开浏览器单个域名的限度,同时联合CDN减速申请。然而这样做须要分片多个TCP申请,TCP的连贯申请的资源耗费比拟大。
后面内容咱们晓得了,HTTP 2 通过改写HTTP数据交互方式为二进制,应用二进制帧的构造实现了应用层的多路复用,所有的二进制帧能够组成流并行能够跑在一个TCP连贯下面,每个Stream都有一个惟一的StreamId,通过每个帧上设置ID(流标识符)在单方向上实现组装来还原报文,接管方须要依据ID的程序拼接出残缺的报文。
应用层上的队头阻塞是解决了,为什么说没有解决TCP队头阻塞?
咱们须要明确HTTP自身是不具备数据传输能力的,尽管HTTP2辨认数据和响应数据的形式变了,然而运载数据的还是TCP协定,而TCP协定实际上基本不意识什么HTTP数据,也不晓得什么流,它只负责保证数据的平安传输。
在一个牢靠的网络中,并发传输和配合没什么问题,HTTP和TCP相互不意识对方也不打紧,然而问题就出在古代社会的网络环境通常是频繁切换的,网络不畅事件时有发生。
在不稳固的网络传输中很有可能呈现TCP数据传输阻塞问题,假如A网站要给B用户一个CSS文件,HTTP晓得要被拆分为三个独立资源的包,依照ID连起来拼成残缺的数据。此时如果数据包1和3都传输过来了,但2在传输过程忽然呈现丢包,此时接管方组装的时候发现ID不间断,这时候是不可能把1前面的数据包3传出去的,TCP的解决形式是将数据包3保留在其接收缓冲区(receive buffer)中,直到它接管到数据包2的重传正本,而后从新拼出残缺的文件再返回给下层利用,HTTP拼接而后能力给浏览器(这至多须要往返服务器一次)。
在HTTP1.X中如果呈现下面TCP队头阻塞状况,能够通过间接抛弃原有的TCP开新的TCP连贯解决问题,尽管开销很大然而至多能够确保传输在失常进行。
而HTTP2在这种状况下就开倒车了,因为HTTP2的理念是一个TCP连贯,所以只能通过期待TCP连贯重传来解决丢包的问题,这种状况下整个TCP连贯都要阻塞,如果是大文件传输,这种体验会更加蹩脚。
论断:
TCP 协定自身的缺点加上HTTP2一个TCP连贯设计,HTTP2的TCP层队头阻塞问题非常显著。HTTP1.X在解决TCP队头阻塞尽管笨,然而理论体验要比HTTP2好得多。
以上这就是TCP的队头阻塞问题。顺带提一句HTTP3 通过了QUIC协定替换掉TCP协定,彻底实现了无队头阻塞的HTTP连贯。
简略解说一下http2的多路复用
HTTP1.X不反对多路复用。同一个域名并发申请会因为浏览器限度在6-8左右,多余连贯会全副阻塞,过来的解决办法是应用多域名和CDN以及缓存服务器减速HTTP1.X。
HTTP1.X的多路复用尝试是管道化,然而它是十分失败的尝试,HTTP2.0 将它变得欠缺和可用。
2.0版本的多路复用指多个申请能够同时在一个TCP连贯上并发,次要借助二进制帧中的标识进行辨别实现链路的复用;
流标识符号示意帧属于哪一个流的,下限为2的31次方,接管方须要依据流标识的ID组装还原报文,同一个Stream的音讯必须是有序的。
总的来说HTTP2的多路复用就是:
- 同域名下所有通信都在单个连贯上实现,打消了因多个 TCP 连贯而带来的延时和内存耗费。
- 单个连贯上能够并行交织的申请和响应,之间互不烦扰(流标识符的存在)。
- 反对双向推送,然而多路复用会造成带宽压力加大。
是否能够在不实现 TLS 的状况下实现 HTTP/2?
能够,然而我不倡议这么干。在 HTTP2中,“h2”示意加密的 HTTP/2,“h2c”示意明文的 HTTP/2,这个c示意"clear text"。
起因如下:
- 只反对h2c的客户端:须要生成一个针对 OPTIONS 的申请。
- 只反对h2c 的服务器:能够应用一个固定的 101 响应来接管一个蕴含降级(Upgrade)音讯头字段的申请。在响应中能够对于不反对的版本进行明确的状态码回绝(505状态码)。
- 不想要解决HTTP1.X的申请:立刻用 REFUSED_STREAM 错误码回绝 stream,激励客户端应用HTTP2 进行重试。
应用明文须要单方向的兜底操作,并且服务实现方通常只能把控服务端这一块,那么还不如间接强制用TLS而间接用HTTPS申请来的间接,非TLS申请的提醒在浏览器的体验好很多。如果是心愿用户尽可能应用HTTP2,则能够应用第三种计划。
简略说一下HTTP/2
答案:[[HTTP - HTTP2 知识点]]
具体内容这里不做过多开展,因为HTTP2实现翻天覆地,开展讲又是一篇长文,答复问题次要针对上面的知识点:
- 兼容HTTP1
- 应用层队头阻塞解决
- 并发传输
- 多路复用
- 二进制帧
- 服务器推送
- HPACK/头部压缩
- 申请优先级
关联:[[HTTP - HTTP2 知识点]]
HTTP/2 连贯须要 TCP_NODELAY 么?
首先看一下TCP对于 TCP_NODELAY
的形容。
If set, disable the Nagle algorithm. This means that segments are always sent as soon as possible, even if there is only a small amount of data. When not set, data is buffered until there is a sufficient amount to send out, thereby avoiding the frequent sending of small packets, which results in poor utilization of the network. This option is overridden by TCP_CORK; however, setting this option forces an explicit flush of pending output, even if TCP_CORK is currently set.
这个参数实际上就是Nagle算法的开关,Nagle算法是在过来带宽和网络通信迟缓的状况下设计的优化伎俩。
Nagle算法是时代的产物,因为过后网络带宽无限,简略了解它做的事件就是把承受到的网络资源不会进行传输而是先放到缓冲区缓冲,等到达到肯定的数量再一次性收回去,当然同时也会设置一个定时器,如果缓存区始终不满,到了定时的工夫同样一并收回,这样能够进步用户的应用体验。
古代的网络环境远没有以前那么瘠薄和低廉,目前TCP/IP协定栈的设置曾经默认把TCP_NODELAY=1
(敞开),然而并不是说这个算法齐全派不上用场,有时候因为单个流的大数据量下载仍然有可能派上用场,
防止放弃 HPACK 状态?
能够通过发送一个 SETTINGS 帧,将状态(SETTINGS_HEADER_TABLE_SIZE
)设置到 0,而后 RST 所有的流,直到一个带有 ACT 设置位的 SETTINGS
帧被接管。
为什么 HPACK 中有 EOS 符号?
HPACK用的是霍夫曼编码,为了避免黑客利用字符空隙进行攻打,同时出于CPU解决效率思考,会通过填充字符串的形式对于字节进行对齐,所以任意字符都有可能会有0-7个位的填充操作。
HPACK 的设计容许按字节比拟霍夫曼编码的字符串,并且填充的时候要求应用EOS符号,同时依据霍夫曼编码的定义字符串数据:字符串文字的编码数据。如果 H 为“0”,则编码数据是字符串文字的原始八位字节。如果H 为 '1',则编码数据是字符串文字的 Huffman 编码。
0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | H | String Length (7+) | +---+---------------------------+ | String Data (Length octets) | +-------------------------------+
为了证实下面的阐述,咱们能够间接浏览 https://datatracker.ietf.org/doc/rfc7541/ 这部分内容,外面存在EOS和霍夫曼编码的一些细节探讨。
因为霍夫曼编码的数据并不总是以八位字节边界完结,在它之后插入一些填充,直到下一个八位字节边界。至避免此填充被误会为字符串的一部分文字,代码的最高无效位对应于应用 EOS(字符串结尾)符号。
解码时,编码数据开端的不残缺代码是被视为填充和抛弃。填充严格更长超过 7 位必须被视为解码谬误。填充不是对应于 EOS 代码的最高无效位符号必须被视为解码谬误。霍夫曼编码的字符串
蕴含 EOS 符号的文字必须被视为解码
谬误。
通过下面的探讨以及论证,意思曾经很显著了,简略了解就为了安全性和CPU效率思考,霍夫曼编码会,HPACK又是基于霍夫曼编码进行头部压缩的,为了使标准对立要求EOS的符号进行填充EOS符号。
首部压缩的实现原理是什么?
次要是“两表一码”,动静表,动态表,哈夫曼编码。
动态表负责存储固定的1-61位索引的常见首部字段,动静表用于一些经常出现变动的申请头部或者自定义申请头部,动静表的索引从62开始。
部署问题
如果 HTTP/2 是加密的,我该如何调试?
简略的办法是 NSS keylogging 与 出名的Wireshark 插件(蕴含在最新开发版本中)联合应用。这个办法对 Firefox 和 Chrome 均以及常见支流浏览器可实用。
如何应用 HTTP/2 服务器推送
服务器推送容许服务器无需期待客户端连贯就能够向服务器推送数据,某些时候能够改善用户的应用体验,比方大带宽提早的产品,为了尽可能减少网络连接传输上破费的工夫。
依据申请内容变动而变动申请资源是不明智的,通常会造成缓存生效,详细情况能够查看 RFC 7234 的第 4 节
为了确保资源可能被正确接管,最好的解决形式是应用内容协商机制,应用 accept-encoding 报头字段的内容协商受到缓存的宽泛尊重,然而可能无奈很好地反对其余头字段。
更多面试题
艰深图解HTTP面试题
http常见面试题总结 | 大厂面试题每日一题 (shanyue.tech)