SagePay(支付网关)通知在ASP.Net MVC应用程序中需要很长时间

Dar*_*ung 13 c# asp.net opayo

我们在网站上遇到与高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();
    }
Run Code Online (Sandbox Code Playgroud)

GetTransactionByVendorTxCode方法是一个简单的实体框架调用,所以我已经排除了这一点.

有没有人有这方面的经验,或者他们是否可以看到可能导致此类问题的代码明显错误?

编辑:查看分析器提供的故障表,它表示99.6%的时间花在System.Web.Mvc.MvcHandler.BeginProcessRequest()上.

编辑:使用分析工具New Relic,它表示所有处理时间的22%用于this.sagePayTransactionManager.GetTransactionByVendorTxCode(vendorTxCode)方法.这只是包含对存储库的EF6调用.该调用确实包含谓词参数,而不是预定义条件.可能是查询没有预编译?

Eni*_*ola 1

您可能需要考虑很多事情。

如果 GetTransactionByVendorTxCode 占总处理时间的 22%,那么您将需要简化该方法涉及的所有内容,但仍然继续解决整个处理管道中的其他瓶颈。

您说该方法抽象了对 EF6 的调用,并传入一个谓词表达式,该表达式在Where 子句中使用以构建最终查询。

如果查询很复杂,您是否考虑过委托给 StoredProcedure?由于您要返回一个实体,因此您可以将其挂在 DbSet 上。(对于 DTO,它将挂起 DbContext 的数据库属性)。

此外,您还需要查看谓词中使用的列的索引。当前的记录数是多少?您的查询会导致搜索或扫描吗?您将需要查看生成的查询计划;如果使用 SQL Server 运行查询数据库引擎优化顾问。

也许有关您当前设置的更多详细信息将有助于提供更好的指导。