文章目录
- 面经笔记
- 三次握手过程
- 为啥挥手有个2倍最大报文时长
- 握手成功后协商什么
- 子网掩码的作用是什么
- cookies是什么?服务端怎么设置cookie?
- TCP为啥可靠
- UDP用在啥情况了
- https是安全的,说一下为啥安全,加密过程说下
- ssl协议建立连接的过程说一下
- 502是什么错误?详细说一下
- 什么是快重传
- 进程和线程的区别
- A是B的父进程,A挂了,B的父进程是谁?
- 什么是内核态什么是用户态?你来设计的话,怎么设计内核态
- 知道多路复用吗?为啥select的socket数量是有限的
- 知道redis吗? redis为啥快?
- redis内存满了,在加入新数据会出现啥?
- 知道redis持久化方式吗?说一下
- MySQL了解吗? innodb为啥选择B+树? B+树有啥特点?树高是多少?
- TCP/IP协议包括几层,应用层的主要协议,ICMP协议是第几层协议。简述CMP协议。
- TCP的粘包是什么?TCP如何保证可靠性的?
- java对象的创建方法?
- 读锁和写锁是什么?
- 死锁的原因和防止死锁。
- linux进程间如何通讯的?
- 线程与线程池的区别,如何创建一个线程池,线程池的应用场景。
面经笔记
三次握手过程
第一次握手由客户端发起,向服务器发送SYN包,等待服务器确认
第二次握手由服务器发出,向客户端发出ACK和SYN包,ACK表示服务器接收到了客户端的请求,SYN则是想向客户端确认客户端是否能接收服务器发出的请求
第三次握手由客户端发出,客户端收到服务器的SYN+ACK包,向服务器发送ACK包表示接收到了消息
TCP连接成功,完成三次握手。
为啥挥手有个2倍最大报文时长
首先了解一下什么是2倍最大报文时长:
当客户端第四次挥手的时候,必须经过时间计数器设置的时间2MSL(最长报文段寿命)后,才能进入关闭状态
这主要是有两个原因:
1、为了保证客户端发送的最后一个ACK报文段能够到达服务器。如果客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
2、他还可以防止已失效的报文段。客户端在发送最后一个ACK之后,再经过经过2MSL,就可以使本链接持续时间内所产生的所有报文段都从网络中消失。从保证在关闭连接后不会有还在网络中滞留的报文段去骚扰服务器。
握手成功后协商什么
双方要协商好初始的 seq。
TCP确认哪个包重传,解决包乱序,都是通过seq实现。因此握手目的是互相确认的是seq。
子网掩码的作用是什么
**“子网”**掩码,顾名思义,它就是拿来划分子网的,更准确的说,划分子网的同时,还能通过它知道主机在子网里面的具体ip的具体地址。
作用:
- 方便管理,不同的子网可以相互隔离
- 我们知道,IPv4的ip地址资源比较紧张,实际上整个互联网就是一个巨大的局域网,ip地址有限,那么通过划分子网,如何再在子网里面分配ip地址给子网的主机,这个时候同一一个ip就可以给一整个子网所共用,就解决了互联网ip不够的问题
子网掩码会把一个IP地址按这个划分成这两部分,计算方法是通过把IP地址变成二进制,子网掩码也转成二进制后,两个二进制数按位做 与运算。
比如,一个C类地址,ip: 192.168.0.3 ,子网掩码是:255.255.255.0
- 第一步先转而进制
ip: 192.168.0.3 > 11000000 10101000 00000000 00000011
网掩码:255.255.255.0 > 11111111 11111111 11111111 00000000
- 然后两个二进制按位做与计算
11000000 10101000 00000000 00000011
&
11111111 11111111 11111111 00000000
=
11000000 10101000 00000000 00000000
- 把这个而结果 : 11000000 10101000 00000000 00000000 每个8位转化回变成: 192.168.0.0
192.168.0.0 这个就是我们的网络段(包括了上面说的网络部分和子网部分)
3 就是我们的主机号(主机在子网络里面的标识)
cookies是什么?服务端怎么设置cookie?
cookie是服务器在本地机器上存储的小段文本,并随每一个请求发送至同一服务器,cookie是保存在客户端的。
TCP为啥可靠
1、三次握手保证了服务器和客户端的相互连接
2、确认和重传机制
建立连接时三次握手同步双方的“序列号 + 确认号 + 窗口大小信息”,是确认重传、流控的基础
传输过程中,如果Checksum校验失败、丢包或延时,发送端重传
3、数据排序
TCP有专门的序列号SYN字段,可提供数据re-order
4、流量控制
窗口和计时器的使用。TCP窗口中会指明双方能够发送接收的最大数据量
5、拥塞控制
“慢启动”(Slow Start)、“拥塞避免”(Congestion avoidance)、“快速重传 ”(Fast Retransmit)、“快速恢复”(Fast Recovery)
UDP用在啥情况了
对数据安全性无特殊要求
网络负担非常重,但对响应速度要求高(游戏,视频通话、直播)
https是安全的,说一下为啥安全,加密过程说下
为啥安全?
HTTPS运行在SSL(Secure Socket Layer)之上,添加了加密和认证机制,更加安全。
加密过程:
- 客户端向服务器发起请求
- 服务器返回CA证书公钥给客户端
- 客户端验证CA证书的有效性,生成一个随机密钥(用于对称加密),然后用证书的公钥加密随机值
- 将加密后的密钥发送给客户端
- 客户端用私钥解密密钥
- 用密钥加密要发送的内容给客户端
- 客户端用密钥解密信息
ssl协议建立连接的过程说一下
- 客户端向服务器发起请求
- 服务器返回CA证书公钥给客户端
- 客户端验证CA证书的有效性,生成一个随机密钥(用于对称加密),然后用证书的公钥加密随机值
- 将加密后的密钥发送给客户端
- 客户端用私钥解密密钥
- 用密钥加密要发送的内容给客户端
- 客户端用密钥解密信息
502是什么错误?详细说一下
- 2xx状态码:操作成功。200 OK
- 3xx状态码:重定向。301永久重定向;302暂时重定向
- 4xx状态码:客户端错误。400 Bad Request; 401 Unauthorized; 403 Forbidden;404 Not Found
- 5xx状态码:服务端错误。500服务器内部错误。501服务不可用
502 Bad Gateway是指错误网关,可能情况:
在高并发请求下,达到 php-fpm 最大响应数,后续的请求就会出现 502 错误的。
设置单个请求的超时终止时间。还应该注意到 php.ini 中的 max_execution_time 参数。当请求终止时,也会出现 502 错误的。
查看下数据库进程是否有大量的 locked 进程,数据库死锁导致超时,前端终止了继续请求,但是 SQL 语句还在等待释放锁,这时就要重启数据库服务了或 kill 掉死锁 SQL 进程了。
什么是快重传
在TCP可靠传输机制中,快重传技术使用了冗余ACK来检测丢包的发生。同样,冗余ACK也用于网络拥塞的检测(丢了包当然意味着网络可能出现了拥塞)。快重传并非取消重传计时器,而是在某些情况下可更早地重传丢失的报文段。
当发送方连续收到三个重复的ACK报文时,直接重传对方尚未收到的报文段,而不必等待那个报文段设置的重传计时器超时。
进程和线程的区别
简单概括:进程是资源分配的最小单位,线程是CPU调度的最小单位。
- 进程(Process)是系统进行资源分配和调度的基本单位,线程(Thread)是CPU调度和分派的基本单位;
- 线程依赖于进程而存在,一个进程至少有一个线程;
- 进程有自己的独立地址空间,线程共享所属进程的地址空间;
- 进程是拥有系统资源的一个独立单位,而线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),和其他线程共享本进程的相关资源如内存、I/O、cpu等;
- 在进程切换时,涉及到整个当前进程CPU环境的保存环境的设置以及新被调度运行的CPU环境的设置,而线程切换只需保存和设置少量的寄存器的内容,并不涉及存储器管理方面的操作,可见,进程切换的开销远大于线程切换的开销;
- 线程之间的通信更方便,同一进程下的线程共享全局变量等数据,而进程之间的通信需要以进程间通信(IPC)的方式进行;
- 多线程程序只要有一个线程崩溃,整个程序就崩溃了,但多进程程序中一个进程崩溃并不会对其它进程造成影响,因为进程有自己的独立地址空间,因此多进程更加健壮
A是B的父进程,A挂了,B的父进程是谁?
B会变成孤儿进程。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:子进程退出了,但是父进程没有用wait或waitpid去获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称为僵尸进程。
什么是内核态什么是用户态?你来设计的话,怎么设计内核态
- 用户态只能受限地访问内存,且不允许访问外围设备,没有占用CPU的能力,CPU资源可以被其它程序获取;
- 内核态可以访问内存所有数据以及外围设备,也可以进行程序的切换。
所有用户程序都运行在用户态,但有时需要进行一些内核态的操作,比如从硬盘或者键盘读数据,这时就需要进行系统调用,使用陷阱指令,CPU切换到内核态,执行相应的服务,再切换为用户态并返回系统调用的结果。
知道多路复用吗?为啥select的socket数量是有限的
因为select 的fd是一个unsigned long型的数组,共16个元素,每一位对应一个fd,所以能监听的数量就是16*64=1024。
知道redis吗? redis为啥快?
- 首先,采用了多路复用io阻塞机制
- 然后,数据结构简单,操作节省时间
- 最后,运行在内存中,自然速度快
redis内存满了,在加入新数据会出现啥?
当内存使用情况达到maxmemory时触发内存回收策略
- 过期键的删除
惰性删除:什么时候执行呢?就是在客户端读取带有超时属性的键时,如果已经超过键值设置的过期时间,则删除并返回空。这样做的目的主要是为了节省CPU成本考虑,不需要单独维护TTL链表来处理过期键的删除。但是,如果单独使用这种方式存在一个问题,如果当前的键值永远不再被访问呢?就不删除了吗?那肯定不行,这就会造成内存泄漏的问题。那Redis是怎么解决的呢?Redis提供了一个定时任务的删除机制来做补充。 - 定时任务删除
Redis内部维护了一个定时任务,默认是每秒运行十次。删除的逻辑如下图:
知道redis持久化方式吗?说一下
在我们安装了redis之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。
RDB操作:RDB其实就是把数据以快照的形式保存在磁盘上.
触发条件:
- save的规则满足条件下(比如60s 修改5次key)就会出发rdb操作
- 执行flushall命令,也会触发rdb规则
- 退出redis,也会产生rdb文件
备份就会自动生成一个dump.rdb
AOF机制,工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
MySQL了解吗? innodb为啥选择B+树? B+树有啥特点?树高是多少?
为啥使用B+树?B+树支持区间查询,因为innodb是关系型数据库对区间查询的需求更加大。
B+树比B树的好处:
- IO次数少:B+树的中间节点只存放索引,数据都存在叶节点中,因此中间节点可以存更多数据,让索引树显得更加矮胖;
- 范围查询效率更高:B树需要中序遍历整个树,而B+树只需要遍历叶节点中的链表;
- 查询效率更加稳定:每次查询都需要从根节点到叶节点,路径长度相同,所以每次查询效率都差不多
B/B+树最高是三层
TCP/IP协议包括几层,应用层的主要协议,ICMP协议是第几层协议。简述CMP协议。
5层:应用层、运输层、网络层、数据链路层、物理层
应用层主要协议:HTTP、FTP
ICMP协议是网络层的协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。
TCP的粘包是什么?TCP如何保证可靠性的?
粘包是指客户端发送的两个包在网络中粘在一起了,服务器只能收到一个包,这样就产生了粘包。
TCP如何保证可靠性:
1、三次握手保证了服务器和客户端的相互连接
2、确认和重传机制
3、数据排序
4、流量控制
5、拥塞控制
java对象的创建方法?
使用new关键字 | } → 调用了构造函数 |
---|---|
使用Class类的newInstance方法 | } → 调用了构造函数 |
使用Constructor类的newInstance方法 | } → 调用了构造函数 |
使用clone方法 | } → 没有调用构造函数 |
使用反序列化 | } → 没有调用构造函数 |
读锁和写锁是什么?
读数据和写数据的时候,会给数据进行上锁,防止在读数据或者写数据的时候产生错误。
死锁的原因和防止死锁。
原因:多个进程抢占共享的资源,导致进程互相不能正常运行的僵死状态成为死锁。
思索产生的必要条件:
- 互斥:一个资源一次只能被一个进程使用
- 占有并等待:一个资源至少占有一个进程,并等待另一个被其他进程占用的资源
- 非抢占:已经分配给一个进程的资源不能被强制性抢占,只能自愿释放
- 循环等待:若干个进程之间形成一种头尾相接的环形等待资环关系,该环路中的每个进程都在等待下一个进程占有的资源
处理方法:
-
鸵鸟策略:不处理
-
死锁预防:破坏形成死锁的必要条件
- 破坏互斥:允许某些资源被多个进程访问(可用性低)
- 破坏占有并等待:实行资源预分配策略、或者在没有占用资源的时候才能申请资源
- 破坏非抢占式:允许进程抢占被其他进程占有的资源。会降低性能
- 破坏循环等待:对所有资源统一编号,所有经常对资源的请求必须按照需要顺序申请。
-
死锁避免:动态的检测资源分配状态,以确保系统处于安全状态。安全状态指:即使所有进程突然请求需要的所有资源也能存在某种资源分配顺序使得每一个进程允许完成。
-
死锁解除:
- 利用抢占:挂起某些进程,并抢占它的资源。
- 利用回滚:让某些进程回退到足以接触死锁的地步,进程回退时资源释放资源。要求系统保持进程的历史信息,设置还原点
- 利用杀死进程:强制杀死某些进程知道死锁接触为止。
何如检测思索:检测有向图是否存在环;或者使用类似死锁避免的检测算法
linux进程间如何通讯的?
- 管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
- 命名管道:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
- 消息队列:消息队列是有消息的链表,存放在内核中并由消息队列标识符标识。消息队列解决了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- 信号:信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
- 共享内存:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
- 信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。
- 套接字(Socket):套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
线程与线程池的区别,如何创建一个线程池,线程池的应用场景。
多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。
假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。
如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。
一个线程池包括以下四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。