ASP.NET WebAPI 和 IIS 中的请求时间不一致

Inconsistent request timings in ASP.NET WebAPI and IIS

问题

我正在测试我们的 AngularJS + ASP.NET WebAPI 应用程序之一的性能。我观察到的奇怪的事情是 在 Fiddler 中以不同的时间执行完全相同的查询

不仅在服务器上而且在我的本地计算机上也观察到这种行为。

详情

该应用程序使用 Chrome 进行测试,并使用 ASP.NET WebAPI (Microsoft.AspNet.WebApi version 5.2.2) 和 Angular JS version 1.3.8.

编写

服务器是 Windows Server 2008 R2,SQL Server 2008 和 IIS 7.5。

我的本地机器是 Windows 8.1,Visual Studio 2013 和 SQL Server 2014。

我注意到根据 Fiddler,完全相同的查询在不同的时间执行(蓝色的查询是相同的,白色的查询是另一种类型的完全相同的查询):

例如查询号码26的详细时间是:

Request Count:   1
Bytes Sent:      583        (headers:517; body:66)
Bytes Received:  3,844      (headers:260; body:3,584)

ACTUAL PERFORMANCE
--------------
ClientConnected:    17:26:25.099
ClientBeginRequest: 17:27:26.544
GotRequestHeaders:  17:27:26.544
ClientDoneRequest:  17:27:26.544
Determine Gateway:  0ms
DNS Lookup:         0ms
TCP/IP Connect: 0ms
HTTPS Handshake:    0ms
ServerConnected:    17:26:25.102
FiddlerBeginRequest:    17:27:26.544
ServerGotRequest:   17:27:26.544
ServerBeginResponse:    17:27:26.554
GotResponseHeaders: 17:27:26.554
ServerDoneResponse: 17:27:26.554
ClientBeginResponse:    17:27:26.554
ClientDoneResponse: 17:27:26.554

    Overall Elapsed:    0:00:00.010

查询号码28的详细时间是:

Request Count:   1
Bytes Sent:      583        (headers:517; body:66)
Bytes Received:  3,844      (headers:260; body:3,584)

ACTUAL PERFORMANCE
--------------
ClientConnected:    17:26:25.099
ClientBeginRequest: 17:27:29.104
GotRequestHeaders:  17:27:29.104
ClientDoneRequest:  17:27:29.104
Determine Gateway:  0ms
DNS Lookup:         0ms
TCP/IP Connect: 0ms
HTTPS Handshake:    0ms
ServerConnected:    17:26:25.102
FiddlerBeginRequest:    17:27:29.104
ServerGotRequest:   17:27:29.104
ServerBeginResponse:    17:27:29.616
GotResponseHeaders: 17:27:29.616
ServerDoneResponse: 17:27:29.616
ClientBeginResponse:    17:27:29.616
ClientDoneResponse: 17:27:29.616

    Overall Elapsed:    0:00:00.512

正如我所说,它们是完全相同的查询(相同的 headers、相同的数据等)。

查询28在查询26后1-2秒执行。

问题

造成这种行为的主要原因是什么?应该去哪里找问题?奇怪的是查询先快后慢再快等等,我没有理由认为问题与数据有关缓存。

如何精确测试服务器上的时间以找到 0.0100.512 秒之间的差异? 差异超过 50 倍。

这不是 angular 问题,但我将如何解决此问题:

  1. 使用类似这样的东西chrome extension for a REST API client to make requests to your endpoint. (you could also use something like: http://jmeter.apache.org/,但设置起来更复杂)
  2. 运行这20次又省了次
  3. 清空数据库,只填充您为此请求所需的表 - 只需几行数据。
  4. 运行工具20次-存储次数。他们一致吗?如果此时它们不一致,我会将代码视为罪魁祸首。

    • 您是否正在调用任何外部服务?
    • 除了执行查询之外,服务在加载数据时是否还执行其他操作?
    • 使用像 dotTrace 这样的探查器来查看什么比它应该花费更多的时间。 (实际上你应该从一开始就使用它)
  5. 如果时间仍然一致,请在数据库中加载更多数据,直到时间开始不一致。然后分析查询并开始优化它们。

现在,根据时间的不一致程度,我假设该服务在加载该数据时做了其他事情:外部服务调用.. 某事。

您写 "the exact same queries",但这些查询中究竟发生了什么?

您正在查询 SQL 服务器数据库吗?

声明看起来如何?

您在查询中还做了什么?

可能的影响因素太多,所以为了做出有根据的猜测,我需要一些关于您的查询的更详细的信息。

要check/note的几件事:

1).你安装了 Glimpse 了吗? http://getglimpse.com/ 如果没有,我会从 nuget 安装它,这将使您深入了解整个管道并帮助您跟踪这些延迟的来源。

*** 下面是更一般的性能提示 **

2).您是否在发布到服务器时在 Web 配置中禁用了调试?如果不先这样做。我希望您的本地电脑与服务器的行为略有不同,我假设您在本地开发电脑上使用 iis express?它与服务器上的 iis 具有不同的性能特征(虽然我不希望如此)因此不要过度受此指导。 Glimpse 将成为您最好的朋友:-)

3).如上所述,这同样适用于会话状态。如果您没有充分的理由使用它,请将其关闭(默认情况下处于打开状态)- 在某些情况下它可能会成为性能杀手。

好吧,如果您能与我们分享在服务器上执行的代码,以及奇数和偶数请求之间的区别是什么,那将非常有帮助。

我在这里做了很多假设,所以请原谅任何愚蠢的错误。

我以前见过这种行为,在那种情况下它与SqlServer 的执行计划缓存有关.

您可以在 Internet 上找到大量关于此的信息,简而言之,在执行查询之前,SqlServer 的引擎会进行一些计算并确定检索该查询数据的最佳方式。这给您的查询时间增加了额外的负担,SqlServer 知道并缓存该执行计划,以便以后可以重用它。

我不知道有关它的所有细节,但如果我不得不猜测,我会说某些东西正在使该缓存无效,因此需要每隔一段时间重新计算一次。造成这种情况的常见原因是 order byjoin 子句不同,这可能取决于发送到方法的数据。

另一个可能性查询的结果本身被缓存,并且过段时间就失效了。

正如我所说,这是不看代码的大胆猜测,但我真的认为检查一下是个好主意。

一种简单的测试方法是检查时间是否变化,如果您一遍又一遍地重复发送完全相同的请求,同时不发送不同的请求。

希望对您有所帮助。

您很可能看到以下情况之一:

  1. IIS 应用程序池回收/清理(当设置为在所有内容关闭后回收时可能会发生这种情况)

  2. .NET GC 收集(不太可能)

  3. SQL 服务器相关延迟(查询执行计划缓存和内存数据)

要排除#3,请尝试 运行 SQL 服务器分析器与 fiddler 同时使用,看看是否可以从数据库中识别延迟(要么确认它在数据库中,否则它将确认数据库在两种情况下的响应相同)。

对于#2,除了尝试减少内存占用和重用数据结构之外,您实际上无能为力;但如上所述,它不太可能是问题的原因。

对于 #1,您应该能够更改 IIS 配置以确保不会发生这种情况。