五月份关于序章科技,腾讯云和腾讯视频,晓信科技的面试题以及答案,抽空整理成博文与大家分享一下。
一 、TCP相关基础知识
三次握手过程
刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态,进行三次握手:
第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c)。此时客户端处于SYN_SENT
状态。
- 首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。
第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于SYN_RCVD
的状态。
- 在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。
第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于ESTABLISHED
状态。服务器收到 ACK 报文之后,也处于ESTABLISHED
状态,此时,双方已建立起了连接。
- 确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。
四次挥手的过程
刚开始双方都处于 ESTABLISHED 状态,假如是客户端先发起关闭请求。四次挥手的过程如下:
第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1
状态。
- 即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入
FIN_WAIT1
(终止等待1)状态,等待服务端的确认。
第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于CLOSE_WAIT
状态。
- 即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入
CLOSE_WAIT
(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2
(终止等待2)状态,等待服务端发出的连接释放报文段。
第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于LAST_ACK
的状态。
- 即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入
LAST_ACK
(最后确认)状态,等待客户端的确认。
第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于TIME_WAIT
状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入CLOSED
状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于CLOSED
状态。
- 即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入
TIME_WAIT
(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED
状态。
三次握手过程中可以携带数据吗?
第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据。
什么是半连接队列?
服务器第一次收到客户端的 SYN 之后,就会处于SYN_RCVD
状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。
TCP是通过什么机制保障可靠性的?
- 应用数据被分割成TCP认为最适合发送的数据块。这和UDP完全不同,应用程序产生的数据报长度将保持不变。
- 超时重传
- 需要确认
- 保持首部和数据的检验和
- 数据后重新排序
- 丢弃重复
- 流量控制
从四个方面进行回答,ACK确认机制、超时重传、滑动窗口以及流量控制,深入的话要求详细讲出流量控制的机制。
tcp为什么要三次握手和四次挥手?
三次握手:
- 第一次握手: 确认客户端的发送能力、服务端的接收能力是正常的。
- 第二次握手: 客户端可以知道客户端的接收,发送能力正常,服务器自己的发送、接收能力也正常。但是服务器端还不知道。
- 第三次握手: 服务端可以知道客户端的接收,能力正常,服务器自己的发送、接收能力也正常。
四次挥手:
- 原因是因为tcp是全双工模式 ,接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据。
tcp怎么保证有序传输的?
为了保证数据包的可靠传递,发送方必须把已发送的数据包保留在缓冲区;
并为每个已发送的数据包启动一个超时定时器;
如在定时器超时之前收到了对方发来的应答信息(可能是对本包的应答,也可以是对本包后续包的应答),则释放该数据包占用的缓冲区;
否则,重传该数据包,直到收到应答或重传次数超过规定的最大次数为止。
接收方收到数据包后,先进行CRC校验,如果正确则把数据交给上层协议,然后给发送方发送一个累计应答包,表明该数据已收到,并且可以携带数据。
ISN(Initial Sequence Number)是怎么生成的?
ISN = M + F(localhost, localport, remotehost, remoteport).
M是一个计时器,这个计时器每隔4毫秒加1。
F是一个Hash算法,根据源IP、目的IP、源端口、目的端口生成一个随机数值。要保证hash算法不能被外部轻易推算得出,用MD5算法是一个比较好的选择。
TCP初始化序列号不能设置为一个固定值,因为这样容易被攻击者猜出后续序列号,从而遭到攻击。
二、 操作系统
描述线程、进程以及协程的区别? 描述线程、进程以及协程的定义和区别,顺便描述Go语言中三者的使用。
一、定义
1、进程
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
2、线程
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。
3、协程
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
二、区别:
1、进程多与线程比较
线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别:
1) 地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,它们共享进程的地址空间,而进程有自己独立的地址空间
2) 资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
3) 线程是处理器调度的基本单位,但进程不是
4) 二者均可并发执行
5) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
2、协程多与线程进行比较
1) 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。
2)协程切换完全在用户空间进行,线程切换涉及特权模式切换,需要在内核空间完成。
为什么在用户态和内核态之间切换调度成本比较高?
三、 网络编程相关基础
网络IO模型有哪些?
- 同步模型(synchronous IO)
- 阻塞IO(bloking IO)
- 非阻塞IO(non-blocking IO)
- 多路复用IO(multiplexing IO)
- 信号驱动式IO(signal-driven IO)
- 异步IO(asynchronous IO)
具体描述:
I/O多路复用中select/poll/epoll的区别?
- Select
工作原理:
从用户空间拷贝fd_set到内核空间,也即从当前程序拷贝fd_set数组进内核。
对所有的fd进行一次poll操作,即把当前进程挂载到fd上。
poll操作过程中select会唤醒所有的队列中节点,进行遍历,得到它们的掩码(不同的掩码表示不同的就绪状态)。
如果所有设备返回的掩码都没有显示任何的事件触发,就去掉回调函数的函数指针,进入有限时的睡眠状态,再恢复和不断做poll,再作有限时的睡眠,直到其中一个设备有事件触发为止。
- 只要有事件触发,系统调用返回,将fd_set从内核空间拷贝到用户空间,回到用户态,用户就可以对相关的fd作进一步的读或者写操作了。
三个缺点:
select最大的缺陷就是单个进程所打开的FD是有一定限制的,它由FD_SETSIZE设置,默认值是1024。
对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。
需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。
poll
poll本质上和select没有区别,但它没有最大连接数的限制,原因是它是基于链表来存储的。
poll还有一个特点是“水平触发”
,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。epoll
- 基本原理:
epoll支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就绪态,并且只会通知一次
。还有一个特点是,epoll使用“事件”的就绪通知方式
,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd
,epoll_wait便可以收到通知。
优点:
没有最大并发连接的限制
,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)。效率提升,不是轮询的方式,不会随着FD数目的增加效率下降
。只有活跃可用的FD才会调用callback函数;即Epoll最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关
,因此在实际的网络环境中,Epoll的效率就会远远高于select和poll。内存拷贝
,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销
。
LT(level trigger)和ET(edge trigger)
LT模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,
应用程序可以不立即处理该事件
。下次调用epoll_wait时,会再次响应应用程序并通知此事件。ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,
应用程序必须立即处理该事件
。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。
四、 HTTP 相关基础
客户端访问url到服务器,整个过程会经历哪些?
https://blog.fundebug.com/2019/02/28/what-happens-from-url-to-webpage/
描述HTTPS和HTTP的区别。
HTTP1.0、HTTP1.1 和 HTTP2.0 的区别。
RESTful 风格 API 有什么优点和缺点
对比 GraphQL 与RESTFUL两种HTTP API的差异
五、 数据库和中间件的基础知识
5.1 Redis
描述一下redis有哪些数据结构。
基础的数据结构有5种,String/List/Hash/Set/Zset,高级数据结构HyperLogLog/BitMap/BloomFilter/GeoHash。
Redis的LRU实现
Redis的持久化机制
zset跳表的数据结构
https://redisbook.readthedocs.io/en/latest/internal-datastruct/skiplist.html
Redis的分布式锁
5.2 Mysql
MVCC 实现原理?
通过在每行记录后面保存两个隐藏的列来实现的。
- 行的创建时间。
行的过期时间(或删除时间)。
当然存储的并不是实际的时间值,而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。
SELECT
只查找版本早于当前事务版本的数据行。
行的删除版本要么未定义,要么大于当前事务版本号。
INSERT
为新插入的每一行保存当前系统版本号作为行版本号。
DELETE
为删除的每一行保存当前系统版本号作为行删除标识。
UPDATE
为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。
Sql 如何优化?
https://www.ulovecode.com/2020/05/03/数据库/mysql/高性能mysql(4)/#more
5.3 Kafak
Kafka的复制机制
消息中间件选型分析
Kafka中的选举
Kafka为什么吞吐量大、速度快?
HW机制
六、 算法以及数学题及智力题
随机打乱一个数组
给出一个数字 n,代表 n 个人的序号,偶数是女生奇数是男生,假设 n 人想出去团建,行政需要帮忙订房间每个房间 2 个人,男女不能同房,要写一个函数 randomRoom 随机出配出所有房间的人。
一个路口30分钟内有车通过的概率是90%,则5分钟内有车通过的概率是多少?
12箱黄金,每箱100块,每块一两。有个贪官,把某一箱的每块都磨去一钱。请称一次找到不足量的那个箱子。
七、 架构
秒杀业务
如何设计秒杀系统? - 网易云的回答 - 知乎 https://www.zhihu.com/question/54895548/answer/259218876
DNS 负载均衡算法
https://blog.csdn.net/lonelymanontheway/article/details/89222159
水平扩展和垂直扩展
每秒100W请求,架构如何优化
Redis分布式锁服务器挂了怎么办?
https://xiaomi-info.github.io/2019/12/17/redis-distributed-lock/