返回题库高级 .NET 刷题ASP.NET Core 问答题 · 第 4 / 5 篇

ASP.NET Core 问答 04:后台任务、实时通信、测试与可观测性

061 BackgroundService.ExecuteAsync 应如何退出?

难度: 基础

查看参考答案

结论: 持续监听 stoppingToken,在取消后停止取新任务并完成有界清理

原因: 宿主停止依赖协作式取消,忽略令牌会拖延关机

边界: 长阻塞调用需使用可取消 API 或设置超时

最小示例: while (!stoppingToken.IsCancellationRequested)

062 为什么不能把重要后台任务直接 Task.Run 后丢弃?

难度: 基础

查看参考答案

结论: 应把任务交给受宿主管理的队列或持久化作业系统

原因: fire-and-forget 无法可靠观察异常、重试和关机完成状态

边界: 请求作用域结束后捕获的 scoped 依赖还可能已释放

最小示例: 端点只入队任务 ID,由 Hosted Service 消费

063 如何设计有界后台队列?

难度: 基础

查看参考答案

结论: 使用有容量的 Channel 并明确满载时等待、拒绝或丢弃策略

原因: 无界队列在流量峰值会耗尽内存,有界队列提供背压

边界: 队列只是进程内机制,重启不保证任务不丢

最小示例: Channel.CreateBounded 配合写入超时

064 周期任务如何避免重叠执行?

难度: 基础

查看参考答案

结论: 串行等待每次任务完成,或使用互斥和跳过策略明确控制重叠

原因: 定时触发频率高于处理耗时时会累积并发

边界: 多实例部署还需分布式租约或幂等设计

最小示例: PeriodicTimer 循环中 await 本轮工作

065 后台任务如何处理重试?

难度: 基础

查看参考答案

结论: 只重试瞬时故障,使用退避、抖动、次数上限和死信或告警

原因: 无限快速重试会放大故障,非幂等操作可能产生重复副作用

边界: 重试前要判断异常类型并使用幂等键

最小示例: 数据库超时退避重试,参数错误直接失败

066 SignalR Hub 生命周期有什么特点?

难度: 基础

查看参考答案

结论: Hub 实例通常按调用临时创建,不应把连接状态保存在 Hub 字段

原因: 跨调用状态应放外部存储或按连接管理的服务

边界: 多节点还需 backplane 或托管服务广播跨节点消息

最小示例: 用 Clients.User 向用户连接发送

067 SignalR Group 能否作为安全边界?

难度: 进阶

查看参考答案

结论: 不能,加入组前仍需认证授权,组成员关系是路由便利机制

原因: 组名和客户端参数可被操纵,重连后成员关系也需恢复

边界: 发送敏感消息前应重新依据可信身份判断

最小示例: 服务端根据授权结果 AddToGroupAsync

068 SignalR 如何应对慢客户端?

难度: 进阶

查看参考答案

结论: 限制消息大小和缓冲、传播取消,并监控积压与断开

原因: 无限缓存会让单个慢连接消耗大量内存

边界: 不同传输和部署拓扑会影响背压行为

最小示例: 对高频更新合并或丢弃过期状态

069 gRPC Deadline 与取消如何传播?

难度: 进阶

查看参考答案

结论: 客户端设置 Deadline,服务端读取 ServerCallContext.CancellationToken 并传给下游

原因: 超时信号不会强制终止忽略取消的代码

边界: 已提交的外部副作用不会自动回滚,需要幂等与补偿

最小示例: 数据库查询接收调用取消令牌

070 gRPC 流式调用要注意哪些并发约束?

难度: 进阶

查看参考答案

结论: 单个流的读写通常遵守单读单写,并处理背压、取消和中途失败

原因: 任意并发写同一响应流可能异常或乱序

边界: 长流还要限制消息大小和连接持续时间

最小示例: 用单写者通道汇聚多个生产者

071 WebApplicationFactory 能覆盖哪些集成行为?

难度: 进阶

查看参考答案

结论: 它启动测试宿主,可覆盖路由、中间件、认证、序列化和服务组合

原因: 它比直接 new Controller 更接近真实请求,但外部依赖仍需隔离

边界: 测试配置必须避免连接生产资源

最小示例: factory.CreateClient 发送 HTTP 请求

072 测试中如何替换认证?

难度: 进阶

查看参考答案

结论: 注册专用 AuthenticationHandler 产生确定 Claims,并分别测试 401、403 和成功路径

原因: 全局绕过授权会掩盖缺失策略和端点元数据错误

边界: 替身身份必须与生产策略使用的 Claim 契约一致

最小示例: 测试处理器返回指定用户

073 为什么 EF Core 查询常需要真实数据库集成测试?

难度: 进阶

查看参考答案

结论: 内存集合无法验证 SQL 翻译、排序、空值和数据库特定行为

原因: Mock DbSet 容易复制 LINQ to Objects 语义而产生假阳性

边界: 可以用容器化目标数据库或隔离测试库

最小示例: 验证复杂 GroupBy 生成的 SQL

074 单元测试为什么不应依赖 Thread.Sleep?

难度: 进阶

查看参考答案

结论: Sleep 依赖机器时序且拖慢测试,应注入 TimeProvider 或可控信号

原因: CI 负载变化会让固定等待产生随机失败

边界: 真正的超时集成测试仍需合理上限和诊断

最小示例: FakeTimeProvider 推进虚拟时间

075 日志、指标和追踪分别回答什么问题?

难度: 实战

查看参考答案

结论: 日志记录离散事件,指标展示聚合趋势,追踪连接一次请求的跨服务路径

原因: 三者互补,单独堆日志很难解释延迟分布和依赖链

边界: 高基数标签会增加指标成本,敏感数据不应进入遥测

最小示例: traceId 关联日志与 span

076 OpenTelemetry 在 ASP.NET Core 中如何接入?

难度: 实战

查看参考答案

结论: 注册 Activity、Meter 和日志导出器,并配置资源与采样

原因: 自动仪表化提供基础跨度,自定义业务步骤仍需显式埋点

边界: 导出失败不能阻塞核心请求,采样会影响可见细节

最小示例: 为支付调用创建自定义 ActivitySource

077 Correlation ID 与 Trace ID 有什么关系?

难度: 实战

查看参考答案

结论: Trace ID 是分布式追踪标准上下文,业务 Correlation ID 可作为额外关联字段

原因: 优先传播标准 W3C traceparent,避免每个服务自造不兼容头

边界: 外部传入关联值要校验长度和字符,防止日志注入

最小示例: 日志作用域加入 TraceId

078 健康检查应区分哪些状态?

难度: 实战

查看参考答案

结论: Liveness 判断进程是否应重启,Readiness 判断实例能否接流量

原因: 把所有依赖抖动都判为不存活会触发重启风暴

边界: 检查必须有超时并避免高成本查询

最小示例: 数据库不可用时 readiness 失败但进程仍存活

079 生产异常应该记录几次?

难度: 实战

查看参考答案

结论: 在能够处理或最终边界记录一次,并携带结构化上下文

原因: 每层捕获后都记录再抛出会产生重复噪声

边界: 若某层增加独有诊断,可用作用域或异常数据而不是重复整段堆栈

最小示例: 全局异常处理器记录未处理异常

080 如何诊断偶发高延迟?

难度: 实战

查看参考答案

结论: 结合延迟分位数、分布式追踪、运行时计数器、数据库和依赖指标定位阶段

原因: 平均值会隐藏尾延迟,单次日志也无法说明总体频率

边界: 诊断工具本身有成本,应先低开销观测再针对性采样

最小示例: 从 P99 慢请求 trace 下钻 SQL span

官方资料

当前分类

ASP.NET Core 问答题

查看全部分类 →
  1. 01ASP.NET Core 问答 01:宿主、管道、配置与依赖注入20 题
  2. 02ASP.NET Core 问答 02:Minimal API、MVC、路由、绑定与验证20 题
  3. 03ASP.NET Core 问答 03:认证、授权、安全、缓存与状态20 题
  4. 04ASP.NET Core 问答 04:后台任务、实时通信、测试与可观测性20 题
  5. 05ASP.NET Core 问答 05:EF Core、部署、性能与生产故障排查20 题
ESC

输入关键词开始搜索