如何预热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预热。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值