问题描述
需要帮助来理解为什么第一个请求总是比其他请求花费更长的时间。测试案例:通过POST请求发送二进制数据。
这是Azure Application Insights中的典型图片,在同一分钟内触发了2个系列的4个请求:
服务器端
只需将二进制数据读入字节数组。
具有Azure功能:
[FunctionName("TestSpeed")]
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Anonymous,"get","post",Route = "TestSpeed")]HttpRequestMessage req,Binder binder,ILogger log)
{
Stopwatch sw = new Stopwatch();
sw.Start();
byte[] binaryData = req.Content.ReadAsByteArrayAsync().Result;
sw.Stop();
return req.CreateResponse(HttpStatusCode.OK,$"Received {binaryData.Length} bytes. Data Read in: {sw.ElapsedMilliseconds} ms");
}
或使用ASP.NET Web应用程序API:
public class MyController : ControllerBase
{
private readonly ILogger<MyController> _logger;
public MyController(ILogger<MyController> logger)
{
_logger = logger;
}
[HttpPost]
public IActionResult PostBinary()
{
_logger.LogInformation(" - TestSpeed");
var sw = new Stopwatch();
sw.Start();
var body = Request.Body.ToByteArray();
sw.Stop();
return Ok($"Received {body.Length} bytes. Data Read in: {sw.ElapsedMilliseconds} ms");
}
}
客户端(仅用于测试)
使用.NET Framework,C#控制台应用程序...
private static void TestSpeed()
{
Console.WriteLine($"- Test Speed - ");
string requestUrl = "https://*******.azurewebsites.net/api/TestSpeed";
string path = "/Users/temp/Downloads/1mb.zip";
byte[] fileToSend = File.ReadAllBytes(path);
var sw = new Stopwatch();
for (int i = 0; i < 4; i++)
{
sw.Reset();
sw.Start();
var response = SendFile(fileToSend,requestUrl);
sw.Stop();
Console.WriteLine($"{i}: {sw.ElapsedMilliseconds} ms. {response}");
}
}
private static string SendFile(byte[] bytesToSend,string requestUrl)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.ContentLength = bytesToSend.Length;
using (Stream requestStream = request.GetRequestStream())
{
// Send the file as body request.
requestStream.Write(bytesToSend,bytesToSend.Length);
requestStream.Close();
}
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (var sr = new StreamReader(response.GetResponseStream()))
{
var responseString = sr.ReadToEnd();
return responseString;
}
}
}
catch (Exception e)
{
return "ERROR:" + e.Message;
}
}
我尝试过的嫌疑人:
- 这不是冷启动/热身的事情,因为该行为在同一分钟内重复出现。.并且我也启用了“始终开启”。
- 比较HTTP和HTTPS-相同的行为。
- Azure函数与ASP.NET核心Web API应用程序-相同的行为。我注意到的唯一区别是使用函数,在调用之前,请求内容已在服务器端完全接收:
ASP.NET web API: 5512 ms. Received 1044397 bytes. Data Read in: 3701 ms
Function App: 5674 ms. Received 1044397 bytes. Data Read in: 36 ms
- 发送1Kb与1Mb-行为相同,首次通话需要花费更多。
- 在Localhost上运行服务器-行为类似,但与远程服务器相比,差异要小得多! (看起来网络距离很重要……)
有一些会话创建开销吗?如果是这样,为什么这么大? 我能做些什么?
解决方法
由于您的测试界面位于Web程序中,因此即使您打开常开开关,该程序发生了什么或该程序是否可以保持活动状态,您也需要举一张支持票以与官员确认。从开发人员的角度来看,建议您像这样进行测试:
-
重新部署Web界面后,首先使用功能应用进行测试,然后使用webapi界面进行测试以比较测试时间。
-
再次重新部署,首先使用webapi进行测试,然后使用function app进行测试。比较测试时间。
-
不需要部署。在第二次测试的基础上,5分钟后再次测试。使用功能app或webapi的顺序无关紧要。查看测试时间数据。
我认为问题应该在IIS上。 IIS本身具有回收机制。该应用程序将长时间不使用,或在部署后会有延迟。建议与官员确认。