计算机基础与 Linux 面试题精选
Java 后端真实面试专题 · 计算机基础与 Linux 篇
网络、操作系统和部署题看似基础,面试官常用它们判断你能不能解释线上现象。下面每题按“标准答 → 原理/边界 → 命令或代码 → 项目落地”展开。示例中的服务名、端口和指标只是演示,回答自己的经历时请替换成真实信息。
年限标签:
🟢 3年内🔴 3年+
一、网络
1. 🟢 TCP 三次握手的过程?为什么是三次不是两次?
标准答:TCP 连接建立需要双方确认收发能力和初始序列号。客户端发送 SYN(seq=x) 进入 SYN-SENT;服务端收到后回复 SYN(seq=y)+ACK(ack=x+1) 进入 SYN-RECEIVED;客户端再回复 ACK(ack=y+1),双方进入 ESTABLISHED。第二个报文同时确认客户端的 SYN 并发送服务端自己的 SYN,所以不是四次。
为什么不是两次:如果只有 SYN 和 SYN+ACK,服务端无法确定自己的 SYN 是否成功到达客户端;延迟的旧 SYN 还可能让服务端提前分配资源,形成无效连接。第三个 ACK 让服务端知道客户端确实收到了自己的序列号。TCP 的可靠性还依赖序号、确认、重传、滑动窗口和拥塞控制,握手本身不传业务数据。
拓展:SYN 洪泛会占满半连接队列,可用 SYN Cookie、连接限速和防火墙缓解;客户端重传 SYN 时服务端会重发 SYN+ACK。HTTPS 是 TCP 握手后再做 TLS 握手,HTTP/3 则基于 QUIC/UDP,不能机械套 TCP 流程。连接池能减少反复握手,但要设置空闲超时和健康检查。
往项目引:排查建连问题可用 ss -s、ss -ant state syn-recv、tcpdump -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0'(需权限)。在 Java 服务中,HTTP 客户端连接池复用、合理的 connect/read timeout 能减少冷启动和半连接堆积;回答时说明你观察了什么指标,不要只说“调大超时”。
2. 🟢 TCP 四次挥手的过程?为什么是四次?
标准答:TCP 双向字节流要分别关闭。主动关闭方发送 FIN 表示自己没有更多数据;对方回复 ACK,但仍可继续发送剩余数据;数据发完后对方再发送 FIN;主动方回复最后一个 ACK。因此通常是四个报文,状态会经历 FIN-WAIT、CLOSE-WAIT、LAST-ACK 和 TIME-WAIT。
主动方最后停留 2MSL 是为了让丢失的 ACK 有机会重传,也让旧连接报文在网络中消散,避免新连接误收旧包。CLOSE-WAIT 长时间不消失通常是应用没有关闭 socket;TIME-WAIT 多是主动关闭方的正常现象,不能看到数量大就直接关闭内核保护。
拓展:如果双方恰好同时发送 FIN,流程会合并为同时关闭;RST 是异常中止,不等同于优雅挥手。高并发短连接导致大量 TIME_WAIT 时,优先启用 keep-alive/连接池、检查客户端关闭策略,再在理解风险后调整端口范围和回收参数。
ss -ant state time-wait | wc -l
ss -antp | awk '$1 == "CLOSE-WAIT" {print}'
往项目引:排查连接泄漏时把 CLOSE-WAIT 的 PID、线程栈和代码中的 response/socket 关闭路径对应起来;不要用 kill -9 代替修复。网关和下游客户端都应设置连接复用、最大空闲连接和优雅停机。
3. 🟢 TCP 和 UDP 的区别?分别用在什么场景?
标准答:TCP 面向连接、可靠有序、具备重传、流量控制和拥塞控制,传输的是字节流;UDP 无连接、不保证到达和顺序,保留报文边界,头部开销小、延迟低。TCP 适合 HTTP、数据库、文件传输等“不能丢”;UDP 适合 DNS、实时音视频、在线游戏等“允许少量丢包但更在乎时延”。
可靠并不等于绝对实时:TCP 队头阻塞和重传可能增加尾延迟;UDP 也不是天然更快,应用仍要处理丢包、乱序、拥塞和安全。QUIC 在 UDP 上实现可靠、有序(按流)、TLS 和连接迁移,是 HTTP/3 的基础。
拓展:直播控制信令和媒体数据可以使用不同协议;DNS 既有 UDP 也有 TCP(响应过大、区域传送等)。若必须让 UDP 可靠,可在应用层加序列号、确认、重传和拥塞控制,但这会重新承担 TCP 的复杂度。
往项目引:普通 Java Web 接口通常基于 TCP,不应为了“快”把订单请求改成 UDP。选型时列出可靠性、顺序、最大报文、穿透 NAT、运维和安全要求,再决定 HTTP/TCP、WebSocket、QUIC 或 UDP。
4. 🟢 HTTP 的 GET 和 POST 有什么区别?
标准答:HTTP 方法首先是语义约定,而不是“参数放哪里”。GET 用于读取资源,应该安全、幂等、可缓存;POST 通常用于创建或触发处理,默认不幂等。GET 参数常放 query string,POST 数据通常放 body,但两者都可以有 body,是否接受由协议和服务器实现决定。GET 也有 URL 长度、日志和历史记录暴露敏感参数等实际限制。
| 维度 | GET | POST |
|---|---|---|
| 典型语义 | 查询资源 | 创建/提交处理 |
| 幂等性 | 设计上应幂等 | 需业务保证或幂等键 |
| 缓存 | 浏览器/代理更容易缓存 | 默认不缓存 |
| 数据位置 | query/path 常见 | body 常见 |
| 安全 | 不因 GET 自动安全,仍需鉴权 | 不因 body 自动保密,必须 HTTPS |
拓展:PUT 是幂等的全量替换,PATCH 是部分更新,DELETE 语义上幂等但首次成功后再次调用可能返回 404。POST 重试要携带业务幂等键或 token;敏感信息不能只因为“改成 POST”就认为不会泄露。
curl -G 'https://api.example.test/orders' --data-urlencode 'status=PAID'
curl -X POST 'https://api.example.test/orders' -H 'Idempotency-Key: req-123' -d '{"skuId":1}'
往项目引:接口设计文档写清方法语义、状态码、幂等规则和缓存策略;网关或客户端重试只对明确幂等的请求开启,避免把 POST 的网络重试变成重复下单。
5. 🟢 常见的 HTTP 状态码有哪些?
标准答:
2xx成功:200 OK有响应体,201 Created创建成功,202 Accepted已接收异步处理,204 No Content成功但无 body。3xx重定向/缓存:301永久、302/307临时(307保留方法)、304协商缓存命中。4xx客户端请求问题:400参数/格式错误,401未认证,403已认证但无权限,404资源不存在,409状态冲突,429限流。5xx服务端或网关问题:500未处理异常,502上游响应无效,503暂不可用,504等待上游超时。
状态码只表达大类,业务错误还应有稳定的错误码、可读 message 和 traceId。401 应引导认证,403 不应让客户端盲目重试;429/503 可通过 Retry-After 提示退避。网关返回 502/504 时要区分网关自身、网络和后端服务。
拓展:异步创建适合 202,不要所有成功都返回 200;删除不存在资源是否返回 204 或 404 要统一约定。错误响应不要泄露堆栈、SQL 或内部地址。
往项目引:统一异常处理器把参数校验、认证、权限、冲突和系统异常映射到一致的 HTTP 响应;监控按状态码、业务码和接口维度拆分,避免用“总错误率”掩盖某个关键接口的 409 或 429。
6. 🔴 在浏览器输入一个 URL 到页面展示,发生了什么?
标准答:浏览器先解析 URL,检查缓存和 HSTS;通过 DNS 缓存、递归服务器和权威服务器得到 IP(可能先命中 CDN);与目标建立 TCP 连接,HTTPS 再完成 TLS 握手和证书校验;发送 HTTP 请求,经 CDN/负载均衡/网关路由到应用;应用读取缓存或数据库生成响应;浏览器解析 HTML、CSS、JavaScript,构建 DOM/CSSOM,计算布局、绘制并执行脚本。HTTP/2/3、keep-alive 和缓存可能让连接不在每次请求后关闭。
拓展:DNS 可能返回多个地址,客户端要选择并重试;TLS 校验域名、有效期和信任链;响应可能是压缩、分块或流式。首屏慢要拆成 DNS、连接、服务端 TTFB、资源下载、脚本执行和渲染时间,不能只看后端日志。
往项目引:从后端视角可以顺着“接入层 → 网关鉴权/限流 → 服务 → 缓存/DB → 响应”讲链路,并在每层放 traceId、超时和监控。静态资源用 CDN、动态接口用连接池,能分别降低网络和建连成本。
二、操作系统
7. 🟢 进程、线程、协程的区别?
标准答:进程是资源隔离和分配的基本单位,有独立虚拟地址空间;线程是 CPU 调度基本单位,同进程线程共享堆、文件描述符等资源,但拥有独立栈和寄存器上下文;协程通常是用户态调度的轻量执行单元,切换不必每次进入内核,适合大量 IO 等待。协程是否真正并行取决于底层线程和运行时。
进程切换和通信成本最高但隔离好;线程共享内存、切换较轻但有竞态和死锁风险;协程切换轻但不能阻塞底层线程,否则一批任务都会停住。Java 21 虚拟线程由 JVM 调度到少量平台线程,适合阻塞式 IO 密集场景,但 CPU 密集任务仍需控制并行度。
拓展:多核并行需要多个可运行线程;“协程一定比线程快”是错误表述。线程池大小应根据 CPU/IO、下游容量和压测决定;共享状态仍需同步或采用不可变对象。
往项目引:普通 Spring MVC 请求通常占用平台/虚拟线程,异步任务使用有界线程池;不要用无限创建线程解决 QPS。排查线程问题可结合 jstack、线程池活动数、队列长度和下游连接池指标。
8. 🟢 操作系统为什么要加锁?用户态和内核态了解吗?
标准答:多个执行单元同时读写共享资源会产生竞态,例如“先查余额再扣款”被两个线程交错执行。锁建立互斥、可见性和有序性边界,保护临界区不变量。用户态代码权限低,执行文件、网络、线程阻塞等系统调用时通过陷入切换到内核态;切换和调度都有成本。
锁不是越多越安全:临界区过大降低并发,锁顺序不一致会死锁,读多写少可考虑读写锁或不可变快照。synchronized 可能先在用户态竞争/自旋,竞争激烈时阻塞并进入内核;CAS、无锁结构也不是没有代价,会有自旋、缓存一致性和 ABA 问题。
拓展:用户态/内核态不是“应用线程/系统线程”两套线程;一次上下文切换不一定都由锁触发,IO、时钟和调度也会触发。分布式多进程不能靠 JVM 锁,需要数据库条件更新、Redis 锁或其他协调机制。
往项目引:先用数据库唯一约束/原子更新保护业务不变量,再在必要处缩小 JVM 临界区;线上看到锁等待时,用线程 dump、锁竞争指标和事务耗时定位,不要直接把锁超时调大。
三、Linux 与部署
9. 🟢 常用的 Linux 命令有哪些?
标准答:
| 目标 | 常用命令 | 关注点 |
|---|---|---|
| 文件/文本 | pwd、ls -lah、find、less、grep、awk、sed | 路径、权限、上下文 |
| 进程/资源 | ps -ef、top、vmstat、free -h、df -h、du -sh | CPU、内存、磁盘、IO |
| 网络 | ss -lntp、lsof -i、curl -v、dig、ping | 监听、DNS、连接和响应 |
| 服务/权限 | systemctl、journalctl、chmod、chown | 启停、日志、属主 |
命令选择应围绕“现象 → 假设 → 证据”展开:先看进程和资源,再确认端口与网络,最后定位日志和线程。grep 只负责筛选文本,awk 适合按列聚合,find 适合按路径/时间/大小定位文件;线上不要把递归扫描和高频 du 直接打到繁忙磁盘。
示例排查链:
ps -ef | grep '[j]ava'
PID=12345
top -Hp "$PID"
ss -lntp | grep ':8080'
tail -F /var/log/app/app.log | grep --line-buffered 'ERROR\|traceId'
df -h && free -h
kill -15 先请求优雅退出,确认无响应再评估 kill -9;不要把 rm、chmod -R 作用在不确定的目录。生产命令要记录时间、目标主机和结果,避免误操作。
拓展:df 看文件系统剩余空间,du 看目录占用,两者不一致时要想到“已删除但仍被进程打开的文件”,可用 lsof +L1 排查。CPU 高还要区分用户态、内核态和 IO wait;内存高要结合 RSS、堆 dump 与 page cache,不能只看 free 的 used 数字。
往项目引:把常用组合做成只读诊断脚本,脚本参数白名单化;日志按日期轮转,磁盘和文件描述符接近上限时提前告警。
10. 🟢 一个 jar 包怎么部署到服务器?有哪些启动参数?
标准答:构建阶段生成可复现的 jar,上传到目标目录,校验版本和配置后启动;生产更推荐 systemd、容器或编排平台托管,而不是手工 nohup。JVM 参数、Spring 参数和应用参数要分开管理。
nohup java -Xms512m -Xmx512m \
-XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/lib/app/dump \
-jar app.jar --spring.profiles.active=prod --server.port=8080 \
>> /var/log/app/app.log 2>&1 &
echo $!
-Xms/-Xmx 控制堆初始/最大值,不能脱离容器内存限制;GC 选择要结合 JDK 版本和压测,不能只背 UseG1GC。启动后检查健康接口、端口、日志和依赖连通性,停止时先 SIGTERM 并等待连接排空。
拓展:配置和密钥不要硬编码进 jar 或命令历史;滚动发布要避免新旧版本同时写出不兼容数据;OOM dump 目录必须有空间并设置权限。nohup 适合临时验证,不是完整的进程守护和回滚机制。
往项目引:部署脚本应支持版本目录、软链接切换、健康检查和一键回滚;把 JVM、应用、容器资源指标纳入同一监控面板。
11. 🟢 Docker 是什么?解决了什么问题?常用命令?
标准答:镜像是分层、不可变的应用包,容器是镜像启动后的隔离进程;Docker 利用 Linux namespace/cgroup 隔离进程和资源,共享宿主机内核。它解决依赖打包、环境一致、快速部署和资源隔离问题,但不等于完整虚拟机,也不自动解决数据持久化、网络和安全。
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/app.jar app.jar
USER 10001
ENTRYPOINT ["java", "-jar", "app.jar"]
docker build -t app:2026-08-29 .
docker run --rm --name app -p 8080:8080 --memory=768m app:2026-08-29
docker ps
docker logs -f app
docker inspect app
docker stop app
镜像要固定基础版本、减少层和权限,容器内日志输出到 stdout 由平台采集;数据库等有状态数据要挂载卷或使用外部服务。Kubernetes 负责编排、探活、扩缩容和滚动发布,Docker 本身只负责打包和运行。
拓展:容器限制的 CPU/内存会影响 JVM 感知;--privileged 不应随意使用;镜像中的秘密会进入层历史。多阶段构建可减少编译依赖进入运行镜像。
往项目引:本地用 Compose 起依赖服务,CI 构建并扫描镜像,生产用编排平台配置资源、探针、优雅停机和回滚,不把宿主机源码目录直接挂进生产容器。
12. 🔴 服务的打包发布流程(CI/CD)是怎样的?
标准答:提交代码后触发 CI:检出固定提交、编译、单元/集成测试、静态检查、构建并扫描镜像、推送制品仓库;CD 把同一个不可变制品部署到测试/预发,做健康检查和验收,再按审批、灰度、全量发布;出现异常按版本回滚并保留审计记录。
拓展:数据库变更采用“扩展→切换→收缩”,保证旧版本可读;配置和制品分离;灰度要有自动中止阈值(错误率、p95、核心业务成功率)。不要把“流水线绿了”当作业务验证,至少要有冒烟和回滚演练。
往项目引:在面试中说清分支保护、MR review、制品版本、审批人、部署策略和回滚条件;没有使用某工具时讲流程,不要虚构工具名称或发布规模。
13. 🟢 git 工作流?新来一个任务你怎么开发?
标准答:先同步主干并确认工作区干净,按任务创建短生命周期 feature 分支;小步提交、写清 commit,推送后提 MR/PR,经过自动检查和 review 合并;发布分支只接收经过验证的提交,紧急修复走 hotfix 并回合主干。
git fetch origin
git switch main
git pull --ff-only
git switch -c feature/order-idempotency
# 开发、自测
git add path/to/file
git commit -m "feat: add order idempotency guard"
git push -u origin feature/order-idempotency
merge 保留分支拓扑、操作直观;rebase 使个人分支历史线性,但不要改写已被他人使用的公共分支。冲突解决后必须重新跑测试并检查 git diff --check;不要用强制推送覆盖别人的提交。
拓展:提交前检查敏感信息、生成文件和大文件;回滚优先用 git revert 保留审计。数据库和接口变更要在 MR 中附迁移/兼容说明,避免代码能回滚而数据不能。
往项目引:把任务拆成可 review 的提交,联调前提供接口示例和兼容策略;这比只背 checkout 命令更能体现协作能力。