高级
# 🔴 高级梯队:.NET 底层与性能极限 (181–200)
# 181)JIT 分层编译 (Tiered Compilation)
面试官: .NET Core 的 JIT 是怎么工作的?什么是分层编译?为什么第一次调用慢?
候选人(要点):
- Tier 0 (Quick JIT):快速生成机器码,不做复杂优化,为了加快启动速度(Cold Start)。
- Tier 1 (Optimized JIT):当方法被频繁调用(热点探测,hit count > 30),后台线程会重新 JIT,生成带 PGO (Profile-Guided Optimization) 的高度优化代码。
- OSR (On-Stack Replacement):允许在循环执行过程中替换机器码(.NET 7+)。
面试官追问: 如果我想强制所有代码都用 Tier 1(为了极致吞吐),怎么配置?有什么副作用?(启动变慢)。
# 182)PGO (Profile Guided Optimization)
面试官: 动态 PGO 是 .NET 6/7/8 性能提升的关键,它到底优化了什么?
候选人(要点): 运行时收集数据(如:接口通常是哪个实现类?if 分支通常走哪边?)。优化手段:
- Devirtualization (去虚拟化):把虚方法调用(查 vtable)改成直接调用或内联(Inline)。
- Branch Prediction (分支预测):把大概率走的分支代码排在前面,减少 CPU 流水线中断。
# 183)GC 源码级原理:Card Table
面试官: 跨代引用(Gen 2 对象引用 Gen 0 对象)时,GC 怎么知道?难道要扫描 Gen 2 吗?
候选人(要点): 不扫描。使用 Card Table(写屏障 Write Barrier)。当 Gen 2 对象引用发生变化指向 Gen 0 时,将对应的“卡片”标记为 Dirty。GC 只需扫描 Dirty Cards 即可找到跨代引用,极大减少扫描范围。
面试官追问: 为什么写屏障会影响写入性能?(赋值操作多了几条汇编指令)。
# 184)Zero Allocation(零分配)编码
面试官: 让你写一个高性能 HTTP 路由匹配器,要求 Zero Allocation,你有哪些手段?
候选人(要点):
- Span:代替
string.Substring。 - ArrayPool:代替
new byte[]。 - Struct 替代 Class:对于小对象。
- ref struct:强制栈上分配。
- SkipLocalsInit:跳过栈内存清零(极致微优化)。
面试官追问:stackalloc在循环里用会爆炸吗?(会,栈溢出)。
# 185)SIMD (单指令多数据)
面试官: .NET 里的 Vector<T> 是做什么的?什么场景能提升 10 倍性能?
候选人(要点): 利用 CPU 的 AVX2/AVX-512 指令集,一条指令并行处理多个数据(如 8 个 float)。场景:图像处理、矩阵计算、大数组求和、加密算法。
# 186)Native AOT 局限性
面试官: 既然 AOT 启动快、内存小,为什么不全用 AOT?有什么硬伤?
候选人(要点):
- 无动态 Emit:依赖
Reflection.Emit的库(如旧版 Newtonsoft.Json, Moq, Dapper)无法工作。 - 泛型特化膨胀:所有泛型组合必须在编译期确定,可能导致二进制文件巨大。
- 调试困难。
# 187)Memory Model (内存模型)
面试官: C# 是强内存模型还是弱内存模型?volatile 到底禁止了什么重排?
候选人(要点): ECMA 标准是弱模型,但 CLR 实现(特别是 x64)通常是强模型(Strong Memory Model)。volatile 引入 Acquire/Release Semantics(读屏障/写屏障),禁止读写指令穿过屏障重排。
# 188)Unsafe 代码风险
面试官: fixed 关键字的作用?GC 移动对象时,指针怎么办?
候选人(要点): fixed 会钉住 (Pin) 对象,告诉 GC 在此期间不要移动它。
面试官追问: Pin 住大量小对象会对 GC 造成什么影响?(碎片化,GC 无法压缩堆,导致堆膨胀)。
# 189)ThreadPool 底层:Hill Climbing
面试官: 线程池怎么决定是加线程还是减线程?
候选人(要点): Hill Climbing 算法。采样吞吐量,尝试增加或减少线程,如果吞吐量提升了就继续该方向,否则反向。这是一种自适应控制算法。
# 190)System.IO.Pipelines
面试官: Kestrel 底层为什么要用 Pipelines 而不是 Stream?
候选人(要点): Stream 模式通常伴随 byte[] 拷贝。Pipelines 基于链表式内存块(Segment),解析数据时(如 HTTP Header)可以只传游标(SequencePosition),实现零拷贝解析和背压控制。
# 🔴 高级梯队:Kubernetes 与云原生架构 (201–220)
# 201)K8s 网络模型:CNI
面试官: Pod A 怎么访问 Pod B?CNI 插件(如 Flannel/Calico)到底做了什么?
候选人(要点): K8s 要求扁平网络(所有 Pod 互通)。
- Flannel (VXLAN):封包(Overlay),性能稍差。
- Calico (BGP):纯路由,性能接近物理机。
面试官追问:kube-proxy的 IPVS 模式比 Iptables 模式好在哪?(Iptables 规则多了线性匹配慢,IPVS 基于 Hash 查表快)。
# 202)Ingress Controller 选型
面试官: Nginx Ingress, Traefik, Istio Gateway 怎么选?
候选人(要点):
- Nginx:老牌,稳,性能好,配置麻烦(Reload 问题)。
- Traefik:云原生,动态配置,支持中间件。
- Istio:如果上了 Mesh 就用它,功能最强(金丝雀、熔断、鉴权)但最重。
# 203)Sidecar 模式资源消耗
面试官: 服务网格(Istio)每个 Pod 都要注个 Envoy,这会带来多少延迟?怎么优化?
候选人(要点): 增加 2-3ms 延迟。优化:使用 eBPF(Cilium)无 Sidecar 模式,或者通过配置裁剪 Envoy 的 Filter 链。
# 204)K8s 优雅停机 (Graceful Shutdown)
面试官: 滚动更新时,为什么会有 502 错误?怎么做到零中断?
候选人(要点):
- Pod 状态变为 Terminating。
- K8s 从 Endpoint 摘除 IP(异步)。
- 应用收到 SIGTERM。
问题:步骤 2 和 3 是并行的,应用可能先停了,Endpoint 还没摘,流量还在进。
解法:在preStophook 里sleep 10s,等 Endpoint 摘干净了再停应用。
# 205)Operator 模式开发
面试官: 什么时候需要写 K8s Operator?CRD (Custom Resource Definition) 是什么?
候选人(要点): 当需要管理有状态应用(如 Redis 集群、数据库)的复杂生命周期(备份、扩容、故障恢复)时。CRD 定义配置结构,Controller 协调实际状态趋向期望状态。
# 206)K8s 调度亲和性
面试官: 怎么让 AI 任务只调度到有 GPU 的节点?怎么让服务 A 和服务 B 尽量在同一个节点(为了低延迟)?
候选人(要点):
- NodeAffinity:指定节点标签(GPU=true)。
- PodAffinity:指定和某些 Pod 在一起。
- Taint/Toleration:污点驱逐非授权 Pod。
# 207)HPA 扩容滞后
面试官: HPA 基于 CPU 扩容太慢(流量来了 CPU 飙升才扩,已经晚了),怎么解决?
候选人(要点):
- KEDA:基于事件(如 RabbitMQ 积压量)扩容,更实时。
- CronHPA:已知高峰期(早8点)定时提前扩容。
# 208)云原生存储 CSI
面试官: Pod 漂移到另一台机器,本地磁盘数据丢了怎么办?
候选人(要点): 必须用 PV/PVC 挂载网络存储(EBS/NFS/Ceph)。StatefulSet 保证 Pod 和 PVC 的稳定绑定。
# 🔴 高级梯队:大规模分布式架构 (221–240)
# 221)CAP 理论的工程取舍
面试官: 注册中心(Eureka vs Zookeeper)是 AP 还是 CP?为什么 K8s 选 Etcd (CP)?
候选人(要点):
- Eureka (AP):看重可用性,读到旧列表没关系,别崩就行。
- Zookeeper/Etcd (CP):看重一致性,数据必须对。
K8s 选 Etcd 因为 Cluster State 必须全局一致,不能出现脑裂导致两个 Controller 同时操作资源。
# 222)共识算法:Raft
面试官: Raft 的 Log Replication 过程?Leader 挂了怎么选主?
候选人(要点): 选举(Election)、日志复制(Replication)、安全性(Safety)。核心:大多数(Quorum)。谁的 Log 最新(Term + Index),谁才能当选。
# 223)Gossip 协议
面试官: Redis Cluster 为什么不用 Raft 而用 Gossip?
候选人(要点): Gossip(谣言传播)去中心化,适合大规模节点状态同步(最终一致性),元数据量大。Raft 适合强一致元数据,节点多了性能下降(选举慢)。
# 224)分布式 ID:时钟回拨
面试官: 雪花算法遇到机器时钟回拨(NTP 同步)怎么办?
候选人(要点):
- 抛异常(简单粗暴)。
- 等待(回拨时间短)。
- 借用未来时间(逻辑时钟)。
- 使用备用 WorkerID。
# 225)异地多活 (Multi-Region Active-Active)
面试官: 北京和上海机房同时写,怎么防冲突?
候选人(要点):
- 单元化(Set 化):按 UserID 分片,北方用户走北京,南方走上海。
- 冲突解决:CRDTs(无冲突数据类型)或 Last-Write-Wins(依赖精确时钟)。
- 数据同步:Otter / DTS 双向同步。
# 226)一致性 Hash
面试官: 为什么引入虚拟节点(Virtual Nodes)?
候选人(要点): 解决数据倾斜问题。让少量物理节点也能在环上分布均匀。
# 227)DDoS 防御架构
面试官: 100Gbps 的流量打过来,架构怎么扛?
候选人(要点):
- 高防 IP / 清洗中心(第一道关)。
- CDN:分摊流量。
- 网关层:黑名单、限流。
- 后端:熔断自保。
# 228)Saga 事务模式
面试官: Saga 的编排式(Orchestration)和协同式(Choreography)区别?
候选人(要点):
- 协同式:服务自己发事件,监听事件(去中心化,乱)。
- 编排式:有个中心 State Machine(如 MassTransit Saga),指挥 A 做完 B 做(清晰,单点风险)。
# 🔴 高级梯队:AI 工程化与 LLM 架构 (241–260)
# 241)RAG 架构瓶颈
面试官: RAG 检索回来的片段不相关(检索噪声),导致 LLM 胡说八道,怎么优化?
候选人(要点):
- Re-ranking(重排序):检索出 Top 50,用精排模型(Cross-Encoder)选 Top 5。
- Hybrid Search:向量搜索(语义) + 关键词搜索(BM25)。
- HyDE:假设性文档嵌入(先让 LLM 生成假答案,再拿假答案去搜)。
# 242)向量数据库索引
面试官: HNSW 索引原理?为什么比暴搜快?代价是什么?
候选人(要点): 分层小世界图。跳表思想 + 图遍历。代价:构建慢、内存占用大。
# 243)Semantic Kernel 插件调度
面试官: AI 怎么知道该调哪个插件?Function Calling 原理?
候选人(要点): 将函数签名(Schema)描述放入 Prompt。LLM 输出特定的 JSON 结构,SK 捕获该输出,反射调用本地 C# 方法,再把结果塞回 Prompt 让 LLM 总结。
# 244)Context Window 限制
面试官: 文档太长超过 Token 限制怎么办?
候选人(要点):
- Map-Reduce:分段总结,再总结总结。
- Refine:滚动摘要。
- Sliding Window。
# 245)Agent 规划能力 (ReAct)
面试官: ReAct (Reasoning + Acting) 是什么?
候选人(要点): 思考(Thought) -> 行动(Action) -> 观察(Observation) -> 循环。
# 246)LLM 评测 (Eval)
面试官: 怎么知道新版本的 Prompt 效果好不好?
候选人(要点): 使用 LLM-as-a-Judge(用 GPT-4 给小模型的回答打分)。建立 Golden Dataset。
# 247)数据隐私与合规
面试官: 企业私有数据不能传给 OpenAI,怎么办?
候选人(要点):
- Azure OpenAI(企业协议,不训模型)。
- 本地部署开源模型(Llama 3 / Qwen)。