【发布时间】:2015-01-24 16:24:38
【问题描述】:
我们的网站遇到了与 CPU 使用率高相关的性能问题。在使用分析器时,我们已经确定了一个特定的方法,该方法需要大约 35 秒才能返回。
这是使用称为 SagePay 的支付网关时的回调方法。
我复制了下面这个调用的两个方法:
public void SagePayNotificationReturn()
{
string vendorTxCode = Request.Form["vendortxcode"];
var sagePayTransaction = this.sagePayTransactionManager.GetTransactionByVendorTxCode(vendorTxCode);
if (sagePayTransaction == null)
{
// Cannot find the order, so log an error and return error response
int errorId = this.exceptionManager.LogException(System.Web.HttpContext.Current.Request, new Exception(string.Format("Could not find SagePay transaction for order {0}.", vendorTxCode)));
ReturnResponse(System.Web.HttpContext.Current, StatusEnum.ERROR, string.Format("{0}home/error/{1}", GlobalSettings.SiteURL, errorId), string.Format("Received notification for {0} but the transaction was not found.", vendorTxCode));
}
else
{
// Store the response and respond immediately to SagePay
sagePayTransaction.NotificationValues = sagePayTransactionManager.FormValuesToQueryString(Request.Form);
this.sagePayTransactionManager.Save(sagePayTransaction);
ReturnResponse(System.Web.HttpContext.Current, StatusEnum.OK, string.Format("{0}payment/processtransaction/{1}", GlobalSettings.SiteURL, vendorTxCode), string.Empty);
}
}
private void ReturnResponse(HttpContext context, StatusEnum status, string redirectUrl, string statusDetail)
{
context.Response.Clear();
context.Response.ContentEncoding = Encoding.UTF8;
using (StreamWriter streamWriter = new StreamWriter(context.Response.OutputStream))
{
streamWriter.WriteLine(string.Concat("Status=", status.ToString()));
streamWriter.WriteLine(string.Concat("RedirectURL=", redirectUrl));
streamWriter.WriteLine(string.Concat("StatusDetail=", HttpUtility.HtmlEncode(statusDetail)));
streamWriter.Flush();
streamWriter.Close();
}
context.ApplicationInstance.CompleteRequest();
}
GetTransactionByVendorTxCode 方法是一个简单的实体框架调用,所以我排除了这一点。
有没有人在这方面有任何经验,或者他们是否可以看到可能导致此类问题的代码有任何明显错误?
编辑:查看分析器提供的细分表,它说 99.6% 的时间花在 System.Web.Mvc.MvcHandler.BeginProcessRequest() 中。
编辑:使用分析工具 New Relic,它表示 22% 的处理时间花在 this.sagePayTransactionManager.GetTransactionByVendorTxCode(vendorTxCode) 方法上。这只是包含对存储库的 EF6 调用。该调用确实包含一个谓词参数,而不是预定义的条件。难道是查询没有被预编译?
【问题讨论】:
-
“一个简单的实体框架调用” - 你确定吗?这个代码是什么?
-
看看这个问题/答案,并将调试写入行代码添加到 Application_BeginRequest:stackoverflow.com/a/17073158/82333
-
将 GetTransactionByVendorTxCode 调用更改为虚拟数据结构,并查看响应时间是否发生剧烈变化。如果它在那里你有瓶颈,如果没有,是时候看看其他地方了。
-
请同时分析数据库查询部分。可能是 EF 使用联合等生成一个巨大的查询。这可以提供一些见解
-
Aynchronus 操作是否可用于服务调用?如果是,那么您可以在回调中做事吗?异步操作可以告诉您服务从开始请求到请求完成所用的确切时间。