4.4 KiB
id, title, type, domain, stack, tags, level, related, week
| id | title | type | domain | stack | tags | level | related | week | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cs.network-os.interview | 网络与操作系统面试题 | interview | cs |
|
|
basic |
|
|
网络与操作系统面试题
基础
【基础】从输入 URL 到页面展示,发生了什么?
参考答案:DNS 解析 → TCP 握手(HTTPS 再 TLS 握手)→ 发送 HTTP 请求,经 CDN / 负载均衡 / 网关到应用 → 服务器处理返回 → 浏览器解析 HTML / CSS 构建 DOM 和 CSSOM、布局、绘制、合成,执行脚本。
追问:哪些环节可以优化?→ DNS 预解析、连接复用、HTTP/2、CDN、压缩、缓存、关键资源预加载、减少阻塞脚本。
【基础】为什么 TCP 握手三次、挥手四次?
参考答案:三次握手让双方都确认对方的收发能力并同步初始序号,同时防止过期的连接请求建立连接;挥手时一方发送 FIN 只表示自己不再发送,另一方可能还有数据要发,所以 ACK 和 FIN 分开发送。
追问:TIME_WAIT 有什么作用?→ 确保最后一个 ACK 丢失时能重传,并让旧连接的延迟报文在网络中消失,避免干扰新连接。
【基础】进程、线程、协程的区别?
参考答案:进程是资源分配单位,独立地址空间;线程是调度单位,共享进程资源,由内核切换;协程在用户态调度,切换开销最小,适合大量 I/O 等待。
追问:Go 的 goroutine 和 Python 的协程有什么不同?→ goroutine 由 Go 运行时调度到多个系统线程上,可以利用多核,遇到阻塞自动切换;Python asyncio 协程运行在单线程事件循环中,需要显式 await,阻塞调用会卡住整个循环。
进阶
【进阶】HTTP/1.1、HTTP/2、HTTP/3 的区别?
参考答案:1.1 有持久连接,但同一连接上请求串行(队头阻塞);2 使用二进制分帧和多路复用、头部压缩,但 TCP 丢包仍会阻塞全部流;3 基于 QUIC(UDP),解决传输层队头阻塞,握手更快,支持连接迁移。
追问:HTTP/2 下还需要合并资源、域名分片吗?→ 一般不需要,多路复用已经解决并发问题,域名分片反而增加连接开销。
【进阶】什么是 I/O 多路复用?epoll 为什么比 select 高效?
参考答案:一个线程监视多个 fd,就绪时再处理。select 每次调用都要把全部 fd 拷贝到内核并线性扫描,且有数量上限;epoll 在内核中维护关注列表,就绪的 fd 通过回调放入就绪队列,只返回就绪的,适合大量连接。
追问:水平触发和边缘触发?→ 水平触发:只要还可读就一直通知;边缘触发:状态变化时只通知一次,必须一次读完,否则可能丢失通知。
【进阶】什么是粘包?怎么解决?
参考答案:TCP 是字节流,没有消息边界,多条消息可能合并或被拆分到达。应用层定义边界:固定长度、分隔符(换行,如 SSE、JSON Lines)、长度前缀;接收方用缓冲区增量解析。
追问:长度前缀协议要注意什么安全问题?→ 限制最大帧长度,防止恶意的超大长度值导致内存耗尽。
场景题
【场景题】服务调用下游时出现大量 TIME_WAIT 和 “Cannot assign requested address”,怎么处理?
参考答案:这是作为主动关闭方的短连接过多、本地端口耗尽。根本办法是复用连接(共享 HTTP 客户端、连接池、keep-alive);同时检查超时设置和并发上限;内核参数调整只作为辅助。详见连接问题排查。
追问:怎么确认修复有效?→ 压测对比 TIME_WAIT 数量、建连次数和 P99 延迟。
【场景题】异步 Python 服务中所有请求(包括健康检查)同时变慢,可能是什么原因?
参考答案:事件循环被阻塞:在协程中执行了同步 I/O 或 CPU 密集操作。排查:开启 asyncio 调试模式查看慢回调、采样分析器定位;修复:使用异步客户端、把 CPU 任务放到进程池或任务队列。
追问:为什么健康检查也慢?→ 它和其他请求运行在同一个事件循环中,循环被占用时所有协程都得不到调度。