如何预热Web API,减少初次执行时间

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何预热Web API,减少初次执行时间相关的知识,希望对你有一定的参考价值。

前言

在上次的《差距50倍!为什么Web API第一次执行这么慢?》文章中,我们发现了部分耗时比较大的方法:

  • Microsoft.AspNetCore.Mvc.Infrastructure.ActionInvokerFactory.CreateInvoker - 30.15ms

查看源代码,ActionInvokerFactory使用的是Singleton生命周期:

services.TryAddSingleton<IActionInvokerFactory, ActionInvokerFactory>();

而在构造函数中,会执行排序方法:

public ActionInvokerFactory(IEnumerable<IActionInvokerProvider> actionInvokerProviders)

    _actionInvokerProviders = actionInvokerProviders.OrderBy(item => item.Order).ToArray();

我想,这应该是初次执行时间较长的部分原因。

思路

使用Singleton生命周期的类,在应用的生存期内仅创建一次,相当于静态类。

如果我们在执行Web API之前,就使用过了ActionInvokerFactory,那么在第一次执行Web API时就不会再次初始化它,应该可以减少初次执行时间。

验证

创建一个WarmController,代码非常简单:

[ApiController]
[Route("[controller]")]
public class WarmController : ControllerBase


    [HttpGet]
    public string Get()
    
        return "OK";
    

首先访问Warm接口,再访问WeatherForecast接口,发现初次访问WeatherForecast的执行时间确实大幅减少:


未预热预热后
初次执行时间100ms21ms

实现

但是,不太好每次启动服务后,都先手工访问一下预热接口。

我们可以设置成,在启动后,自动访问一下预热接口。

利用应用程序生存期事件,可以达到这一目的。

修改Startup.cs,代码如下:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime)

    ...

    lifetime.ApplicationStarted.Register(OnAppStarted);


public void OnAppStarted()

    var url = Configuration[WebHostDefaults.ServerUrlsKey];

    var warm = url.Split(';')[0] + "/warm";

    new HttpClient().GetAsync(warm).Wait();

启动后访问WeatherForecast接口,发现确实已经预热过了。

结论

在本文中,我们利用了ASP.NET Core应用程序生存期事件,实现了Web API预热。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“

以上是关于如何预热Web API,减少初次执行时间的主要内容,如果未能解决你的问题,请参考以下文章

初次使用 ansible api 认证问题

N95 上的 J2ME 位置 API - 需要打开诺基亚地图来预热 GPS?

Lambda初次使用很慢?从JIT到类加载再到实现原理

如何预热/预缓存受信任的 Web 活动

如何减少分叉进程以运行可执行文件的 Web 服务器的内存使用量?

初次使用antd-mobile开发时踩的坑