面灵AI→

云徒全栈开发实习转正一面:上线排错、限流手写与权限表设计

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 说一个你做过的最难的项目
  2. 项目上线报错怎么排查?
  3. 如果要收集接口的入参出参,怎么实现?
  4. 慢 SQL 怎么排查和优化?
  5. 介绍一下实习公司组内的情况
  6. 100MB 的文件怎么排序?
  7. 手写实现一个 API 限流?
  8. 哪些情况会导致索引失效?
  9. 从输入 URL 到页面显示,经历了什么?
  10. 你怎么理解 Spring Cloud?
  11. 前后端权限怎么实现,权限表怎么设计?

《参考解析》

上线报错排查要按「先止损再定位」的顺序讲。 第一步是看监控和告警确认影响面(错误率、耗时、受影响接口与用户),必要时回滚上一个版本或摘掉异常实例止血,同时保留现场(日志、堆栈、线程/内存快照)。第二步才是定位:用 traceId 把一次请求在网关、应用、数据库、下游服务上的日志串起来,看是应用异常、依赖超时还是数据问题;没有链路追踪时至少要有统一的日志格式和请求标识。第三步是复盘:把这次故障补进监控(同类错误的告警阈值)、补进用例或回归,而不是改完代码就结束。

入参出参采集的通用做法是 AOP + 结构化日志。 在 Controller 或网关层切一个环绕通知,统一打印方法名、耗时、入参、出参和 traceId,配合 MDC 把 traceId 透传到下游;敏感字段(密码、token、身份证、银行卡)要在切面里脱敏,大对象和文件流不要整体序列化,超长内容截断。工程上更推荐把这类日志落到独立的采集通道(文件 + 日志采集器)而不是业务库里,避免把日志写库变成新的性能瓶颈。

100MB 文件排序的考点是内存装不下。 标准答案是外部归并排序:先把文件分块读入内存(比如每块 64MB),块内用快排/堆排排好写到临时文件,再对所有有序块做 k 路归并,用最小堆每次从各块取最小值输出。工程细节要主动补:临时文件的 I/O 是瓶颈,要顺序读写、加大缓冲区;如果文件本身按行文本,可以按「块边界对齐到换行」避免切坏一行;内存充足时可以直接用 sort 命令的 -S 控制缓冲区大小对比性能。面试官追问「有没有更快的办法」时,可以聊按 key 分桶(hash 分区后每桶独立排序,桶内可直接进内存)和并行归并。

手写 API 限流,先讲算法再讲落地。 固定窗口最简单但存在临界双倍流量问题;滑动窗口按时间分片统计更平滑;令牌桶允许突发、漏桶严格恒速。单机实现用 Guava RateLimiter 或计数器 + 定时补充;分布式场景要用 Redis,把「取令牌 + 扣减 + 判断」写成 Lua 脚本保证原子性,key 维度按用户/IP/接口分,超限返回 429 并带上 Retry-After。真正的工程点是限流粒度(全局限流会误伤,要按接口和调用方分级)、限流后的降级策略(排队、返回兜底数据、还是直接拒绝)以及阈值怎么定(按压测容量留出余量,而不是拍脑袋)。

索引失效的典型场景要能一口气说清。 条件列上做函数运算或隐式类型转换(字符串列传数字)、联合索引不满足最左前缀、like '%xx' 前导模糊、or 连接的条件里有一侧没索引、范围查询之后的列不再走索引、以及优化器因为选择性太差主动放弃索引。分析手段是 EXPLAIN 看 type、key、rows、filtered,8.0 用 EXPLAIN ANALYZE 看真实耗时。要注意「走了索引还是慢」是另一类问题:回表次数太多、扫描行数大、锁等待、以及深分页(limit 100000, 20)——这类要靠覆盖索引、延迟关联或游标解决。

权限表设计的主流是 RBAC。 最小形态是五张表:用户、角色、权限(菜单/按钮/接口)、用户角色关联、角色权限关联;权限粒度再细可以加「资源」与「数据范围」(本人/本部门/全部)两张维度。后端在接口层面用注解或拦截器校验 权限码,数据层面把数据范围拼成 SQL 条件,前端只做展示隐藏(不作为安全边界)。要主动说清的两点:前端隐藏不等于权限控制,真正的边界必须在服务端;以及权限变更的缓存与失效策略,否则改完角色要等缓存过期才生效。

Spring Cloud 的理解要落在「解决分布式带来的哪几个问题」上。 服务注册发现(Nacos/Eureka)、配置中心、远程调用(OpenFeign)、网关(Gateway)、负载均衡、熔断限流降级(Sentinel)、分布式事务(Seata)分别对应「服务怎么找到彼此、配置怎么统一、调用怎么写、流量怎么进来、单点故障怎么隔离、跨服务数据一致性怎么保证」。不要背组件清单,要说清每个组件替代了单体里的什么能力、以及引入之后新增的运维成本。