淘天集团暑期实习-面经


1.讲一下http协议的历史各版本以及主要特点

HTTP/0.9

1991年提出了HTTP/0.9,它最主要的特点就是简单,只有一个GET命令,它虽然简单,但是充分验证了WEB服务的可行性。

HTTP/1.0

HTTP/1.0的最重要的特征就是短连接,也就是每次发送请求的时候都会建立TCP连接,等收到响应就会断开连接。因此在大量请求到来的时候,会反复的创建和销毁连接,性能就会严重下降。

HTTP/1.1

于是HTTP/1.1引入了长连接,这种机制就是说,只要请求的收发双方没有一方明确提出要断开连接,那么就会保留这条TCP连接,减少了TCP连接的三报文握手和四报文挥手的开销。

同时,由于多个请求-响应复用同一条TCP连接,这使得管道网络传输成为可能,也就是说,这时候客户端发送请求时,不必等待前一个请求的响应到达即可发送请求。

问:管道网络传输中,客户端发来的请求1,2,3,服务端返回一定要按顺序1,2,3吗?

是的,这是因为如果不按请求顺序进行响应,就有可能将A的响应给到B,将B的响应给A,造成错乱


但是HTTP/1.1还是有一部分缺点

  • 报文的头部没有做压缩,而只能对body做压缩,因此当头部的体积过大时,将导致网络I/O传输性能下降
  • 将导致队头阻塞问题,虽然使用管道网络传输能够异步发送请求,但是接收响应却是同步的,在这种情况下,如果前面的响应没有发回来,然后后面的请求将一直无法接收到响应
  • 没有提供解决队头阻塞的优先级机制
  • 请求只能从客户端开始,服务器只能够被动响应,服务端无法主动推送服务

HTTP/2.0做了哪些优化?这个问题应该要从两个方面进行回答,第一个方面是安全方面。

HTTP/2引入了TLS1.2+,也就是基于HTTPS的机制,使得HTTP/2的传输变得更加安全了。

第二个是性能方面做了比较大的改动。

1.压缩首部,减少冗余传输

我们刚刚提到HTTP/1.1的报文的头部没有压缩,如果头部比较冗长,就会导致大量冗余的信息在网络中传输。

对于这个痛点,HTTP/2提供的解决方案是,客户端和服务端双方维护一张头信息表,这张表在初始化就被静态写入一些常用的头部字段,当需要使用到这些头部字段(以key-value的形式存储)的时候,就在数据包的头部中封装一个字段header:1 xxxx,其中1代表着这个头部字段在头信息表存在,xxx代表的是索引号,当第一个字段为0的时候,代表不存在,然后后边的这些xxx就是实际上的头部字段,然后传输到对等端的时候,会将这个字段记录到动态表中,方便下次使用

2.全面二进制,节省了传输所需的数据量

HTTP/1.1的数据传输是基于文本传输的,而计算机只能读取二进制数据,因此在发送时需要将文本转换成二进制,在接收时需要将二进制转换成文本。我们采用全面二进制编码之后,比如状态码’2’ ‘0’ ‘0’ ,在http/1.1中需要占用三个字节,然而在HTTP/2中它表示为表示为1100 1000,节省了两个字节。

3.引入Stream机制,解决队头阻塞问题

我们上面提到,客户端发送了请求1,2,3后,服务端响应也要按照1,2,3的顺序来,这就会产生队头阻塞现象,

当第一个请求发送出去之后,由于I/O或者其他原因很长时间都没有收到响应,但是这时候后面的请求又都在排队,从而导致后面的请求无法得到响应,客户端陷入阻塞状态

HTTP/2.0引入了Stream流,它的核心思想就是给响应包加上一个控制字段,让这些包能够标识出来是属于谁的响应。在同一个TCP连接中存在多个Strteam,这多个Stream就代表着同一对请求-响应,他们通过标识StreamId对这些Stream进行标识,从而确保请求能够收到对应的响应。

这样的话,我们假设响应是乱序返回的,比如请求1,2发送,然后响应2,1返回,因为存在StreamId,接收方就能够通过不同Id标识拿到自己想要的数据包。本质上就是IO多路复用,提高了传输性能

4.允许服务端主动推送

主动推送是通过服务器在接收到客户端请求后,主动向客户端推送额外的资源,而不需要客户端单独请求这些资源。 例如,可以提前向客户端发送一些与请求相关的资源,以提高页面加载速度。

服务器向客户端发送一个带有 PUSH_PROMISE 帧的响应,告诉客户端将要推送的资源。 4. 客户端收到 PUSH_PROMISE 帧后,可以决定是否接受推送的资源。

HTTP/2.0的缺陷

它同样存在队头阻塞的问题,只不过它的队头阻塞问题是因为滑动窗口的限制而产生的,也就是队头阻塞产生在TCP层面,先来讲讲它是怎么产生的。

我们假设发送双方维护了一个窗口,然后A同时发送了P1/P2/P3/p4/p5然后等待ACK,然后B能够接收P1/P2

接收完P1之后,但是P2丢掉了,于是它只能够等待P2的超时重传,那么这期间,如果A再发送P3/P4/P5,都不能够再次接收。

HTTP/3.0

既然谈到了优化,那么肯定就是解决HTTP/2所没有解决的问题,HTTP/2没有解决TCP层面的队头阻塞问题

但是这个问题是致命的,因为发送窗口和接收窗口不可能无限制大小,而且为了可靠传输,必须保证数据包的有序接收,因此一个思路就是,修改底层的实现,改为UDP实现

首先要解决的问题是:之前提供的HTTP协议都是TCP的可靠传输,那么我们必须基于UDP实现可靠传输

核心就是上图中的QUIC协议

QUIC协议也有类似的HTTP/2中的Stream的机制,也就是说一条连接中有也有多个Stream,但是每一个Stream并不公用一个窗口,而是有各自的滑动窗口,因此如果流中的包丢失了,只会导致这个请求-响应被阻塞,其他的不被阻塞,这就解决了队头问题

与此同时,QUIC协议还基于UDP协议提高了性能

更快的连接建立

对比与HTTP/1.0、HTTP/1.1的实现,由于TCP+TLS的实现基于内核的TCP传输层和openssl库实现的,因此难以解耦,而QUIC的思路是:在完成连接握手的时候,在帧的首部携带上TLS认证信息,这个过程主要是为了确认双方的连接ID

甚至,在第二次连接的时候,应用数据包可以和 QUIC 握手信息(连接信息 + TLS 信息)一起发送,达到 0-RTT 的效果。

连接的迁移

那么当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立连接。而建立连接的过程包含 TCP 三次握手和 TLS 四次握手的时延,以及 TCP 慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。

而 QUIC 协议没有用四元组的方式来“绑定”连接,而是通过连接 ID 来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。

所以, QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP/2 的多路复用的协议。

QUIC 是新协议,对于很多网络设备,根本不知道什么是 QUIC,只会当做 UDP,这样会出现新的问题,因为有的网络设备是会丢掉 UDP 包的,而 QUIC 是基于 UDP 实现的,那么如果网络设备无法识别这个是 QUIC 包,那么就会当作 UDP包,然后被丢弃。


2.讲一下进程和线程的区别?

本质区别:进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位。

  • 在开销方面:每个进程都有独立的代码和数据空间,程序之间的切换会有较大的开销;线程可以看作轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器
  • 稳定性方面:进程中每个线程如果崩溃了,可能导致整个进程崩溃。而一个进程的崩溃不会影响其他进程。
  • 包含关系来看:没有线程的进程可以看作单线程的,一个线程可以有多个线程。

具体到Java里面,使用main方法的时候其实就是启动了一个JVM进程,而main函数所在的线程就是这个进程中的一个线程,也称为主线程。多个线程共享进程的堆和方法区资源,每个线程有自己的程序计数器、虚拟机栈、本地方法栈。

3.讲一下虚拟内存

虚拟内存是怎么换页的,怎么寻址的?

虚拟内存除了解决内存不够的问题,还有哪些好处?

虚拟内存有哪些坏处?


4.Java中的String,StringBuilder,StringBuffer有哪些区别?

StringBuffer是怎么保证线程安全的?


5.讲一下Java虚拟机的垃圾回收算法

CMS垃圾回收器


6.MySQL的隔离级别,各个级别有什么问题?

为什么InnoDB的默认隔离级别不是串行化?

我答串行化的并发能力很低,在一些业务下可以牺牲数据的准确性来换取性能。在他提示下我才反应过来是MVCC机制解决了RR级别下的幻读问题。


7.讲一下MVCC

mvcc我的回答中提到了undo-log


8.对于MySQL中的日志有哪些了解?

bin-log是什么?

redo-log是怎么保证持久化的?


9.问了项目中的分布式锁


10.你的项目中用到了Netty是吧,讲一下你对bio和nio的了解

nio的底层实现,如epoll这些有没有了解


11.怎样解决缓存穿透问题?

布隆过滤器的底层数据结构


12.反问

Java的竞争太激烈,如果我去转岗到测试开发怎么样?

网有非常多的人渴望到互联网大厂工作,同时也有小部分人在劝退,你是怎么看待这样一份工作的?


文章作者: Fuchanglai
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Fuchanglai !
赏
  目录