ASP.NET Core MVC爬虫请求报错:非并发集合需独占访问
.NET7 ASP.NET Core MVC爬虫请求异常排查与日志优化方案
问题核心分析
- 异常触发特征:仅爬虫类请求(如
Googlebot-Image/1.0)触发,正常用户访问无异常;报错信息为Operations that change non-concurrent collections must have exclusive access,堆栈指向ITempDataDictionary操作,无自定义代码关联。 - 根因推测:爬虫请求的特殊行为(如复用会话标识、并发请求同一会话)导致ASP.NET Core默认的
ITempDataDictionary(基于非并发集合实现)被多线程同时读写,引发线程安全冲突。
排查步骤
- 核查爬虫会话行为
- 检查异常请求的Cookie,确认是否存在多个爬虫请求复用同一
ASP.NET_SessionId或自定义会话标识的情况。 - 在日志中新增
SessionId、User-Agent字段,聚合同一爬虫、同一会话的请求记录,验证并发访问时序。
- 检查异常请求的Cookie,确认是否存在多个爬虫请求复用同一
- 验证ITempData配置与实现
- 当前默认使用
CookieTempDataProvider,可临时切换为SessionStateTempDataProvider,观察异常是否消失,定位是否为Cookie存储的ITempData并发问题。 - 检查项目中是否有针对爬虫请求的特殊中间件,确认是否存在对
ITempData的非线程安全操作。
- 当前默认使用
- 模拟请求复现问题
- 用Postman、curl等工具模拟
Googlebot-Image/1.0请求头,并发发送多请求复现异常场景。 - 将
Microsoft.AspNetCore.Mvc.ViewFeatures日志级别设为Debug,追踪ITempData读写的完整流程,锁定冲突点。
- 用Postman、curl等工具模拟
日志优化建议
- 细化ITempData操作日志:在Program.cs中配置日志过滤器,针对
Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionary开启Debug级别日志,记录每次读写的RequestId、SessionId、操作类型(读/写)。 - 强制关联请求上下文:通过自定义日志 enricher,确保所有异常日志自动携带
User-Agent、RequestUrl、SessionId字段,便于在Seq中快速筛选爬虫请求的完整链路。 - 补充全局异常上下文:在全局异常过滤器中,额外记录请求的完整表单、Cookie信息,避免仅依赖框架堆栈,补充自定义排查数据。
临时缓解方案
- 爬虫请求跳过ITempData操作:通过中间件检测
User-Agent中的爬虫标识,对这类请求跳过ITempData的初始化与写入逻辑。 - 自定义并发安全的ITempDataProvider:基于现有实现封装一层线程安全逻辑,对
ITempData的读写操作加锁,避免并发冲突。
内容的提问来源于stack exchange,提问作者Mike-E
相关产品推荐
相关产品推荐

