宇宙条一面:十道经典面试题解析
前言
有位朋友面试了宇宙条,后端方向。整理了这几道面试真题以及答案,如有错误,欢迎大家留言区讨论哈。金九银十冲刺,面试的小伙伴加油呀。
1.http 请求头里,expire 和 cache-control 字段含义,说说 HTTP 状态码
1.1 expire 和 cache-control 字段含义
Cache-Control 是 HTTP/1.1 的头字段,用来区分对缓存机制的支持情况,请求头和响应头都支持这个属性。通过它提供的不同的值来定义缓存策略。主要有
public、private、no-cache
等值。expires 是 http1.0 的头字段,过期时间,如果设置了时间,则浏览器会在设置的时间内直接读取缓存,不再请求。
1.2 常见 HTTP 状态码
2.https 原理,数字签名,数字证书。
2.1 https 原理
HTTPS = HTTP + SSL/TLS,即用 SSL/TLS 对数据进行加密和解密,Http 进行传输。
SSL,即 Secure Sockets Layer(安全套接层协议),是网络通信提供安全及数据完整性的一种安全协议。
TLS,即 Transport Layer Security(安全传输层协议),它是 SSL 3.0 的后续版本。
Https 工作流程
用户在浏览器里输入一个 https 网址,然后连接到 server 的 443 端口。
服务器必须要有一套数字证书,可以自己制作,也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过。这套证书其实就是一对公钥和私钥。
服务器将自己的数字证书(含有公钥)发送给客户端。
客户端收到服务器端的数字证书之后,会对其进行检查,如果不通过,则弹出警告框。如果证书没问题,则生成一个密钥(对称加密),用证书的公钥对它加密。
客户端会发起 HTTPS 中的第二个 HTTP 请求,将加密之后的客户端密钥发送给服务器。
服务器接收到客户端发来的密文之后,会用自己的私钥对其进行非对称解密,解密之后得到客户端密钥,然后用客户端密钥对返回数据进行对称加密,这样数据就变成了密文。
服务器将加密后的密文返回给客户端。
客户端收到服务器发返回的密文,用自己的密钥(客户端密钥)对其进行对称解密,得到服务器返回的数据。
2.2 数字签名,数字证书
了解过 Https 原理的小伙伴,都知道数字证书这玩意。为了避免公钥被篡改,引入了数字证书,如下:
数字证书构成
公钥和个人信息,经过 Hash 算法加密,形成消息摘要;将消息摘要拿到拥有公信力的认证中心(CA),用它的私钥对消息摘要加密,形成数字签名.
公钥和个人信息、数字签名共同构成数字证书。
3.tcp 连接 client 和 server 有哪些状态,time_wait 状态
3.1 tcp 连接
tcp 连接时,客户端 client 有SYN_SEND
、ESTABLISHED
状态,服务端 server 有SYN_RCVD
、ESTABLISHED
状态。
tcp 三次握手
开始客户端和服务器都处于 CLOSED 状态,然后服务端开始监听某个端口,进入 LISTEN 状态
第一次握手(SYN=1, seq=x),发送完毕后,客户端进入 SYN_SEND 状态
第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1), 发送完毕后,服务器端进入 SYN_RCVD 状态。
第三次握手(ACK=1,ACKnum=y+1),发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态,TCP 握手,即可以开始数据传输。
3.2 time_wait 状态
可以先回忆下 TCP 的四次挥手哈,
TCP 四次挥手
第一次挥手(FIN=1,seq=u),发送完毕后,客户端进入 FIN_WAIT_1 状态
第二次挥手(ACK=1,ack=u+1,seq =v),发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态
第三次挥手(FIN=1,ACK1,seq=w,ack=u+1),发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。
第四次挥手(ACK=1,seq=u+1,ack=w+1),客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态,等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。
TIME-WAIT 状态为什么需要等待 2MSL
2MSL,2 Maximum Segment Lifetime,即两个最大段生命周期
1 个 MSL 保证四次挥手中主动关闭方最后的 ACK 报文能最终到达对端
1 个 MSL 保证对端没有收到 ACK 那么进行重传的 FIN 报文能够到达
4.什么是虚拟内存? 什么是物理内存?
4.1 什么是虚拟内存?
虚拟内存,是虚拟出来的内存,它的核心思想就是确保每个程序拥有自己的地址空间,地址空间被分成多个块,每一块都有连续的地址空间。同时物理空间也分成多个块,块大小和虚拟地址空间的块大小一致,操作系统会自动将虚拟地址空间映射到物理地址空间,程序只需关注虚拟内存,请求的也是虚拟内存,真正使用却是物理内存。
4.2 什么是物理内存
物理内存,指通过物理内存条而获得的内存空间,而虚拟内存则是指将硬盘的一块区域划分来作为内存。
我们常说的物理内存大小,其实是指内存条的大小。一般买电脑时,我们都会看下内存条是多大容量的,话说如果内存条大小是 100G,那这 100G 就都能够被使用吗?不一定的,更多的还是要看 CPU 地址总线的位数,如果地址总线只有 20 位,那么它的寻址空间就是 1MB,即使可以安装 100G 的内存条也没有意义,也只能视物理内存大小为 1MB。
4.3 虚拟内存如何映射到物理内存?
如下图,CPU 里有一个内存管理单元(Memory Management Unit),简称为 MMU,虚拟内存不是直接送到内存总线,而是先给到 MMU,由 MMU 来把虚拟地址映射到物理地址,程序只需要管理虚拟内存就好,映射的逻辑自然有其它模块自动处理。
5.一台机器最多可以建立多少个 tcp 连接,client 端,server 端,超过了怎么办
TCP 连接的客户端机:每一个 ip 可建立的 TCP 连接理论受限于 ip_local_port_range 参数,也受限于 65535。但可以通过配置多 ip 的方式来加大自己的建立连接的能力。
TCP 连接的服务器机:每一个监听的端口虽然理论值很大,但这个数字没有实际意义。最大并发数取决你的内存大小,每一条静止状态的 TCP 连接大约需要吃 3 .3K 的内存。
6.Eureka 原理,是否是强一致性,eureka 集群。宕机了服务还能调用么?Eureka 和 ZooKeeper 对比
6.1 eureka 架构
注册中心是分布式开发的核心组件之一,而 eureka 是 spring cloud 推荐的注册中心实现。
架构图如下:
Eureka Server:提供服务注册和发现,多个 Eureka Server 之间会同步数据,做到状态一致
Service Provider:服务提供方,将自身服务注册到 Eureka,从而使服务消费方能够找到
Service Consumer:服务消费方,从 Eureka 获取注册服务列表,从而能够消费服务
6.2 基于集群的 Eureka 架构图
Eureka server 可以集群部署,多个节点之间会通过 Replicate(异步方式)进行数据同步,保证数据最终一致性。Eureka Server 作为一个开箱即用的服务注册中心,提供的功能包括:服务注册、接收服务心跳、服务剔除、服务下线等。
服务启动后向 Eureka 注册,Eureka Server 会将注册信息向其他 Eureka Server 进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
6.3 宕机了服务还能调用么?
Eureka 挂了,微服务是可以调通的,不过有个前提:provider 的地址没变!如果 provider 换了一个 IP 地址或者端口,这个时候,consumer 就无法及时感知到这种变化,就会调不通。
6.4 Eureka 和 ZooKeeper 对比
Zookeeper 保证 CP(一致性和分区容错性),但是不保证可用性,ZK 的 leader 选举期间,是不可用的。
Eureka 保证 AP(可用性和分区容错性),它优先保证可用性,几个节点挂掉不会影响正常节点的工作。
7.Hystrix 了解嘛?说说 Hystrix 的工作原理
Hystrix 工作流程图如下:
构建命令
Hystrix 提供了两个 Command, HystrixCommand 和 HystrixObservableCommand,可以使用这两个对象来包裹待执行的任务。
执行命令
有四种方式执行 command。分别是:
R execute():同步执行,从依赖服务得到单一结果对象
Future queue():异步执行,返回一个 Future 以便获取执行结果,也是单一结果对象
Observable observe():hot observable,创建 Observable 后会订阅 Observable,可以返回多个结果
Observable toObservable():cold observable,返回一个 Observable,只有订阅时才会执行,可以返回多个结果
检查缓存
如果启用了 Hystrix Cache,任务执行前将先判断是否有相同命令执行的缓存。如果有则直接返回缓存的结果;如果没有缓存的结果,但启动了缓存,将缓存本次执行结果以供后续使用。
4. 检查断路器是否打开 断路器(circuit-breaker)和保险丝类似,保险丝在发生危险时将会烧断以保护电路,而断路器可以在达到我们设定的阀值时触发短路(比如请求失败率达到 50%),拒绝执行任何请求。
如果断路器被打开,Hystrix 将不会执行命令,直接进入 Fallback 处理逻辑。
5. 检查线程池/信号量情况 Hystrix 隔离方式有线程池隔离和信号量隔离。当使用 Hystrix 线程池时,Hystrix 默认为每个依赖服务分配 10 个线程,当 10 个线程都繁忙时,将拒绝执行命令。信号量同理。
6. 执行具体的任务 通过 HystrixObservableCommand.construct() 或者 HystrixCommand.run() 来运行用户真正的任务。
7. 计算链路健康情况 每次开始执行 command、结束执行 command 以及发生异常等情况时,都会记录执行情况,例如:成功、失败、拒绝以及超时等情况,会定期处理这些数据,再根据设定的条件来判断是否开启断路器。
8. 命令失败时执行 Fallback 逻辑 在命令失败时执行用户指定的 Fallback 逻辑。上图中的断路、线程池拒绝、信号量拒绝、执行执行、执行超时都会进入 Fallback 处理。
9. 返回执行结果 原始结果将以 Observable 形式返回,在返回给用户之前,会根据调用方式的不同做一些处理。
8.zookeeper 一致性保证,zab 协议原理,zookeeper 属于哪种一致性,强一致性么,还是最终一致性
Zab 协议,英文全称是 Zookeeper Atomic Broadcast(Zookeeper 原子广播)。Zookeeper 是通过 Zab 协议来保证分布式事务的最终一致性。
Zab 协议是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议 ,是 Zookeeper 保证数据一致性的核心算法。Zab 借鉴了 Paxos 算法,是一种通用的分布式一致性算法。
基于 Zab 协议,Zookeeper 实现了一种主备模型(即 Leader 和 Follower 模型)的系统架构来保证集群中各个副本之间数据的一致性。就是指只有一台 Leader 节点负责处理外部的写事务请求,然后它(Leader)将数据同步到其他 Follower 节点。
Zookeeper 客户端会随机的链接到 zookeeper 集群中的一个节点,如果是读请求,就直接从当前节点中读取数据;如果是写请求,那么节点就会向 Leader 提交事务,Leader 接收到事务提交,会广播该事务,只要超过半数节点写入成功,该事务就会被提交。
Zab 协议要求每个 Leader 都要经历三个阶段:发现,同步,广播。
发现:要求 zookeeper 集群必须选举出一个 Leader 进程,同时 Leader 会维护一个 Follower 可用客户端列表。将来客户端可以和这些 Follower 节点进行通信。
同步:Leader 要负责将本身的数据与 Follower 完成同步,做到多副本存储。这样也是提现了 CAP 中的高可用和分区容错。Follower 将队列中未处理完的请求消费完成后,写入本地事务日志中。
广播:Leader 可以接受客户端新的事务 Proposal 请求,将新的 Proposal 请求广播给所有的 Follower。
9. 聊聊 zookeeper 选举机制
服务器启动或者服务器运行期间(Leader 挂了),都会进入 Leader 选举,我们来看一下~假设现在 ZooKeeper 集群有五台服务器,它们 myid 分别是服务器 1、2、3、4、5,如图:
9.1 服务器启动的 Leader 选举
zookeeper 集群初始化阶段,服务器(myid=1-5)依次启动,开始 zookeeper 选举 Leader~
服务器 1(myid=1)启动,当前只有一台服务器,无法完成 Leader 选举
服务器 2(myid=2)启动,此时两台服务器能够相互通讯,开始进入 Leader 选举阶段
2.1. 每个服务器发出一个投票
服务器 1 和服务器 2 都将自己作为 Leader 服务器进行投票,投票的基本元素包括:服务器的 myid 和 ZXID,我们以(myid,ZXID)形式表示。初始阶段,服务器 1 和服务器 2 都会投给自己,即服务器 1 的投票为(1,0),服务器 2 的投票为(2,0),然后各自将这个投票发给集群中的其他所有机器。
2.2 接受来自各个服务器的投票
每个服务器都会接受来自其他服务器的投票。同时,服务器会校验投票的有效性,是否本轮投票、是否来自 LOOKING 状态的服务器。
2.3. 处理投票
收到其他服务器的投票,会将被人的投票跟自己的投票 PK,PK 规则如下:
优先检查 ZXID。ZXID 比较大的服务器优先作为 leader。
如果 ZXID 相同的话,就比较 myid,myid 比较大的服务器作为 leader。
服务器 1 的投票是(1,0),它收到投票是(2,0),两者 zxid 都是 0,因为收到的 myid=2,大于自己的 myid=1,所以它更新自己的投票为(2,0),然后重新将投票发出去。对于服务器 2 呢,即不再需要更新自己的投票,把上一次的投票信息发出即可。
2.4. 统计投票
每次投票后,服务器会统计所有投票,判断是否有过半的机器接受到相同的投票信息。服务器 2 收到两票,少于 3(n/2+1,n 为总服务器),所以继续保持 LOOKING 状态
服务器 3(myid=3)启动,继续进入 Leader 选举阶段
3.1 跟前面流程一致,服务器 1 和 2 先投自己一票,因为服务器 3 的 myid 最大,所以大家把票改投给它。此时,服务器为 3 票(大于等于 n/2+1),所以服务器 3 当选为 Leader。服务器 1,2 更改状态为 FOLLOWING,服务器 3 更改状态为 LEADING;
服务器 4 启动,发起一次选举。
4.1 此时服务器 1,2,3 已经不是 LOOKING 状态,不会更改选票信息。选票信息结果:服务器 3 为 3 票,服务器 4 为 1 票。服务器 4 并更改状态为 FOLLOWING;
服务器 5 启动,发起一次选举。
同理,服务器也是把票投给服务器 3,服务器 5 并更改状态为 FOLLOWING;
投票结束,服务器 3 当选为 Leader
9.2 服务器运行期间的 Leader 选举
zookeeper 集群的五台服务器(myid=1-5)正在运行中,突然某个瞬间,Leader 服务器 3 挂了,这时候便开始 Leader 选举~
变更状态
Leader 服务器挂了之后,余下的非 Observer 服务器都会把自己的服务器状态更改为 LOOKING,然后开始进入 Leader 选举流程。
每个服务器发起投票
每个服务器都把票投给自己,因为是运行期间,所以每台服务器的 ZXID 可能不相同。假设服务 1,2,4,5 的 zxid 分别为 333,666,999,888,则分别产生投票(1,333),(2,666),(4,999)和(5,888),然后各自将这个投票发给集群中的其他所有机器。
接受来自各个服务器的投票
处理投票
投票规则是跟 Zookeeper 集群启动期间一致的,优先检查 ZXID,大的优先作为 Leader,所以显然服务器 zxid=999 具有优先权。
统计投票
改变服务器状态
10. 算法:给定一个字符串 s ,请你找出其中不含有重复字符的最长连续子字符串的长度。
可以使用滑动窗口实现,代码如下:public int lengthOfLongestSubstring2(String s) {int n = s.length();if (n <= 1) return n;int maxLen = 1;
来源:https://mp.weixin.qq.com/s/65rE8STmiU-pHeSnZY_7xQ
评论