总结一下遇到的面试题-网络篇(自用)

TCP篇

1. TCP为什么是可靠的?

从基础概念出发,TCP是面向连接的基于字节流的通信协议,从连接管理的角度来说:TCP通过三次握手建立连接,确保通信双方有正常收发能力;通过四次挥手释放连接,确保所有数据被正确接收并妥善处理。

这里的可靠指的是报文的可靠传输,换一句话说就是如何保证报文不重不丢:TCP是基于字节流的,每一个字节都有唯一的序列号,这解决了报文重复的问题;接收端接收数据后会回复ACK确认号,这解决了丢包的问题;为了确保数据能够到达,在没有收到ACK的一定时间内,会触发发送方超时重传;另一方面,由接收方主导的流量控制能够避免接收方太多数据处理不过来。这里要注意流量控制和拥塞控制的区别,拥塞控制注重的是尽可能在保证网络不崩溃的前提下,最大化利用带宽。

除了保证不丢不重,还要保证报文不被损坏修改,发送端在发送数据前会计算校验和,接收端接收后会重新计算对比,如不正确接收端会丢弃。

从这个问题延申到队列消息如何不丢不重,可以发现有许多共通之处:投递语义大多实现是At least once重复投递(对应超时重传),通过唯一ID或数据库唯一键约束实现去重(对应唯一序列号),通过ACK机制实现不丢消息,在拉模式下的消费者天然具备流量控制的能力等等。落实到具体实现上会有所不同,不过从共通之处不难进一步归纳出高可用(可靠性)的一些本质:冗余、故障应对、负载控制(均衡),这个话题就更宽泛了,此处不再赘述。

2. TCP故障之:第一次/第二次/第三次握手丢失了怎么办?第一次/第二次/第三次/第四次挥手丢失了怎么办?

这个问题其实和上一个问题息息相关,理解TCP为什么可靠就能理解TCP是如何应对故障的:TCP的可靠性来自确认、重传和状态机三大机制。握手和挥手不过是相对特殊的控制报文,也会遵循这些机制:对于所有报文都会有确认机制,如果确认丢失,发送方会超时重传,状态机确保状态不会乱入,对于最终结果来说要么成功建立/关闭连接,要么在多次重试失败后放弃。具体要注意的是对于最后一次握手,服务器没收到 ACK,会保持在 SYN_RCVD 状态一段时间,等待重传。如果客户端已经进入 ESTABLISHED 状态,它会继续发送数据,服务器在收到数据时也能确认连接已建立。对于最后一次挥手丢失的话服务器重试会等到客户端ACK或者超时关闭。

3. TCP为什么需要三次握手?为什么需要四次挥手?

  • 三次握手:保证双方收发能力正常,避免旧连接干扰,并同步序列号。
  • 四次挥手:保证双方都能安全关闭连接(全双工通信需要双向都关闭),避免数据丢失,并通过 TIME_WAIT 清理残余报文。
  • 4. TCP是绝对可靠的吗?

    世界上当然没有绝对可靠的东西啦~网络故障、网络拥塞、防火墙、中间代理的干扰、校验和冲突等等都可能导致数据的丢失损坏。

    5. 如何设计使得UDP变得靠谱?

    这个问题和问题1本质上是一样的,按照TCP的可靠性保证来回答就可以了:序列号、确认应答、连接管理、校验和、超时重传、流量控制等等,不过UDP本身已经是传输层协议了,所以这些设计都是在UDP之上应用层实现,其中QUIC是可靠UDP的集大成者,它解决了TCP的队头阻塞、连接迁移、握手延迟等痛点。

    HTTP篇

    1. HTTP和HTTPS的区别?HTTPS的加密过程说一下?

    简单来说, HTTPS = HTTP + SSL/TLS, 它通过加密、认证和完整性保护解决了HTTP的安全问题。HTTPS的加密过程也就是SSL/TLS握手,在握手过程中首先客户端会发送生成的随机数、支持的加密算法、TLS的支持版本,服务端会发送自己的数字证书和密钥交换信息;然后客户端验证证书并且生成预主密钥,然后用服务器的公钥加密发送给服务器,这一步采取了非对称加密;最后双方通过固定的算法生成相同的会话密钥,利用对称加密传输数据,握手确认结束开始通信。

    2.为什么要用RPC,和HTTP有什么区别,如何设计RPC

    HTTP是一种超文本传输协议,有规定的状态码和头部,是一种具体的协议;RPC则是一种通信范式或调用方式,可以基于HTTP、TCP、UDP或者自定义的应用层协议来实现。公司内实现的RPC相比于通用易用的HTTP更注重高效、强类型、服务治理等方面:HTTP数据格式多为文本格式(JSON/XML),可读性好但是解析开销大,RPC多为二进制格式(Protobuf、Thrift),体积小、序列化/反序列化速度快;RPC性能比HTTP更高,使用二进制传输、连接复用、头部精简等等。HTTP和RPC并不是对立的概念,例如gRPC是基于HTTP/2的RPC框架,它利用了HTTP/2多路复用、流控等特性,但是在此之上又定义了严格的Protobuf消息格式和服务定义。

    简单来说,RPC框架的本质:在传输层之上,根据业务需求定制一套高效的通信协议,封装传输细节同时提供服务治理、负载均衡、序列化等附加功能。这种自定义通信协议的事情非常常见,例如Agent开发中的MCP本质上是一个自定义的、用于Agent调用工具、有利于 AI 系统设计的应用层协议。

    理解了RPC,就可以考虑如何设计一个RPC了,可以考虑的方面包括但不限于:传输层和应用层的协议选取,序列化方式的选取,连接管理,负载均衡、服务发现和注册中心、容错和高可用、监控与可观测性等等治理能力的支持。例如一个最小的RPC可用系统可以选择HTTP/2作为应用层协议,采取Thrift作为序列化方式,使用Channel来管理连接,通过底层的Socket进行通信,采用Hash或者一致性哈希进行负载均衡,进一步扩展系统则可以加入服务发现、指标收集、监控指标等等。

    客户端调用设计好的RPC的流程通常包含以下几步:

    • 输入:用户业务代码传入的请求参数(强类型对象)
    • 调用后NameService获取IP,然后LoadBalance选择IP,Connect连接IP(连接池)
    • Write Request:将请求参数序列化为字节流,通过Socket发送给服务器
    • Wait Request:阻塞等待服务器响应并在收到后唤醒线程,如果超时也唤醒线程并且抛出异常
    • Metric上报:记录本次调用的状态信息,用于监控、告警和性能分析
    • 输出:返回给业务代码的响应对象,同时触发指标上报状态落盘(如调用日志、统计信息)

    整理了一下午,本人才疏学浅,如有错误之处请多多指教

    全部评论

    相关推荐

    评论
    1
    1
    分享

    创作者周榜

    更多
    牛客网
    牛客网在线编程
    牛客网题解
    牛客企业服务