.NET WEB API多并发请求处理:GetNonce接口压测空引用异常求解
问题根因与修复方案
根因分析
你遇到的并发场景下空引用异常,核心是两类问题:
- 代码中缺少必要的空值校验,部分分支下返回对象为null直接抛出异常
- 依赖的服务类可能存在线程不安全实现,并发时共享变量被篡改导致返回结果为null
最容易触发你当前报错的两个隐藏点:
- 调用
SendGetRequestToKMS返回空值时,你没有对response赋值,最终return的response为null直接抛出空引用 - 依赖的
ProxyService、CertificateValidation等类如果内部使用了静态变量存储请求上下文,并发时多个请求会互相篡改值,导致返回的customers、custID等对象为null,后续直接访问属性时抛出异常
修复步骤
1. 新增dynamic请求参数空校验
你直接访问custReq的动态属性,没有校验字段是否存在,若请求缺mpn/manufacturer字段会直接返回null,调用ToString时抛异常:
if (custReq.mpn == null || custReq.manufacturer == null) { customerResponse.responseMsg.StatusCode = HttpStatusCode.BadRequest; return ResponseMessage(customerResponse.responseMsg); } string mpnStr = custReq.mpn.ToString(); string manufacturerStr = custReq.manufacturer.ToString();
2. 新增客户端证书与客户ID空校验
X509Certificate2 clientCertforCustomer = Request.GetClientCertificate(); if (clientCertforCustomer == null) { customerResponse.responseMsg.StatusCode = HttpStatusCode.Unauthorized; return ResponseMessage(customerResponse.responseMsg); } string custID = certificateValidation.CustomerInfoFromClientCert(clientCertforCustomer); if (string.IsNullOrEmpty(custID)) { customerResponse.responseMsg.StatusCode = HttpStatusCode.Unauthorized; return ResponseMessage(customerResponse.responseMsg); }
3. 新增代理服务返回结果空校验
var customers = proxyService.GetCustomerMPNInfo(custID, mpnStr); if (customers == null || customers.CustomerID != custID || customers.CustomerMPN != mpnStr) { customerResponse.responseMsg.StatusCode = HttpStatusCode.Unauthorized; return ResponseMessage(customerResponse.responseMsg); }
4. 新增命令集合空校验
customerDetails = proxyService.GetMPNCommands(mpnStr); if (customerDetails == null || customerDetails.Cust_Commands == null) { customerResponse.responseMsg.StatusCode = HttpStatusCode.Unauthorized; return ResponseMessage(customerResponse.responseMsg); } foreach (var commandItem in customerDetails.Cust_Commands) { if (commandItem == null || string.IsNullOrEmpty(commandItem.CommandName)) { continue; } // 原有命令处理逻辑 }
5. 修复KMS请求返回空值的分支逻辑
string result = reqHandler.SendGetRequestToKMS(newReq, token, "Nonce"); if (string.IsNullOrEmpty(result)) { customerResponse.responseMsg.StatusCode = HttpStatusCode.InternalServerError; return ResponseMessage(customerResponse.responseMsg); } // 原有result拆分处理逻辑直接保留即可
并发优化建议
- 不要每个请求都新建
HttpClient,改为全局单例复用,避免高并发下socket耗尽:
// 在控制器类中定义静态单例 private static readonly HttpClient _httpClient = new HttpClient();
- 检查
ProxyService、CertificateValidation、TokenGenerator、RequestHandler的内部实现,移除请求相关的静态变量,改为局部变量存储,避免并发时数据互相篡改 - 如果
ProxyService是WCF客户端,建议使用单例或池化管理,不要每次请求都新建销毁
内容的提问来源于stack exchange,提问作者Maldanna Gk
相关产品推荐
相关产品推荐

