今天这篇文章我们来聊一聊如何提升并优化ASP.NET Core应用程序的性能,本文的大部分内容来自翻译,当然中间穿插着自己的理解,希望对大家有所帮助!话不多说开始今天的主题吧!
我们都知道性能是公共网站取得成功的关键因素之一。如果一个网站的响应时间超过3秒,那么用户通常不会再此光顾(此网站)。谷歌,Bing,百度以及其他搜索引擎也更倾向于推荐优化后的,移动友好的以及响应速度更快的网站。
作者:依乐祝
原文地址:https://www.cnblogs.com/yilezhu/p/10507984.html
大部分内容翻译自:https://www.c-sharpcorner.com/article/10-tips-to-improve-performance-of-asp-net-core-application/
这里我们举一个例子:我们有多个搜索引擎,如Google、Bing、百度、搜狗等等;然而,我们更喜欢Google或Bing,因为这些搜索引擎速度非常快,可以在3-4秒内获得结果。如果这些搜索引擎的响应速度超过10秒,你还会使用它们吗?我认为大伙应该不会用了吧。如今的用户最不能容忍的想必就是等待了吧。
今天,我们将学习一些有助于提高ASP.NET Core网站性能的一些小技巧。希望大家能够有所收获。
我们都知道ASP.NET Core是微软提供的一个免费的、开源的、跨平台的Web开发框架。它不是ASP.NET的升级版本,但它是一个从头开始完全重写的框架,它附带了ASP.NET MVC和ASP.NET Web API的单一编程模型。
在这里,我不打算讨论ASP.NET Core及其特性。如果您是ASP.NET Core的新手,您可以阅读我的ASP.NET Core实战教程《.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划》
下面我们就开始今天的主题,如何提升ASP.NET Core应用程序的性能的技巧开始吧。
尽量使用ASP.NET Core的最新版本
ASP.NET Core的第一个版本是在2016年与VisualStudio 2015一起发布的,现在我们有了ASP.NET Core3.0,每一个新版本都越来越好。最新的ASP.NET Core 3.0的主要更新如下:
- Razor组件的改进。现在2个项目合并成单个项目模板,Razor组件支持端点路由和预渲染,Razor组件可以托管在Razor类库中。还改进了事件处理和表单和验证支持。
- 运行时编译。它在ASP.NET Core 3.0模板中被禁用,但现在可以通过向项目添加特殊的NuGet包来打开它。
- Worker Service 模板。需要编写Windows服务还是Linux守护进程?现在我们有了Worker Service 模板。
- gRPC模板。与谷歌一起构建的gRPC是一种流行的远程过程调用(RPC)框架。此版本的ASP.NET Core在ASP.NET Core上引入了第一等的gRPC支持。
- Angular模板使用Angular 7. Angular SPA模板现在使用Angular 7,在第一次稳定释放之前,它将被Angular 8替换。
- SPA-s的身份验证。Microsoft通过此预览为单页应用程序添加了现成的身份验证支持。
- SignalR与端点路由集成。小变化 - 现在使用端点路由定义SingalR路由。
- SignalR Java客户端支持长轮询。即使在不支持或不允许WebSocket的环境中,SignalR Java客户端现在也可以使用。
友情提示:在构建新的ASP.NET Core项目时,不要忘记选择最新版本。VisualStudio 2019预览版现在已经支持ASP.NET Core 3.0了。
尽量避免任何层的同步调用
在开发ASP.NET Core应用程序时,尽量避免创建阻塞的调用。阻塞调用是指当前请求未完成之前会一直阻止下一个执行的调用。阻塞调用或同步调用可以是任何东西,可以是从API中获取数据,也可以是执行一些内部操作。您应该始终以异步方式执行调用。
尽量使用异步编程(ASYNC-AWAIT)
异步编程模型是在C#5.0中引入的,并变得非常流行。ASP.NET Core使用相同的异步编程范例来使应用程序更可靠、更快和更稳定。
您应该在代码中使用端到端异步编程。
让我们举一个例子;我们有一个ASP.NET CoreMVC应用程序,中间有一些数据库的操作。正如我们所知道的,它可能有很多分层结构,这都取决于用户的项目架构,但是让我们举一个简单的例子,其中我们有Controller》Repository 层等等。让我们看看如何在控制器层编写示例代码。
[HttpGet]
[Route("GetPosts")]
public async Task GetPosts()
{
try
{
var posts = await postRepository.GetPosts();
if (posts == null)
{
return NotFound();
}
return Ok(posts);
}
catch (Exception)
{
return BadRequest();
}
}
接下来的代码然是了我们如何在repository 层实现异步编程。
public async Task<List<PostViewModel>> GetPosts()
{
if (db != null)
{
return await (from p in db.Post
from c in db.Category
where p.CategoryId == c.Id
select new PostViewModel
{
PostId = p.PostId,
Title = p.Title,
Description = p.Description,
CategoryId = p.CategoryId,
CategoryName = c.Name,
CreatedDate = p.CreatedDate
}).ToListAsync();
}
return null;
}
使用异步编程避免TASK.WAIT或TAST.RESULT
在使用异步编程时,我建议您避免使用Task.Wait和Task.Result并尝试使用WAIT,原因如下:
- 它们阻塞线程直到任务完成,并等待任务完成。等待同步阻塞线程,直到任务完成。
- Wait 和 Task.Result 在AggregateException中包含所有类型的异常,并在在执行异常处理时增加复杂性。如果您使用的是等待await 而不是 Task.Wait和Task.Result的话,那么您就不必担心异常的处理了。
- 有时,它们都会阻塞当前线程并创建死锁。
- 只有在并行任务执行正在进行时才能使用Wait 和Task.Result 。我们建议您不要在异步编程中使用它。
下面让我们分别演示下正确使用以及不建议使用Task.Wait 的例子,来加深理解吧!
// 正确的例子
Task task = DoWork();
await task;
// 不建议使用的例子
Task task = DoWork();
task.Wait();
下面让我们分别演示下正确使用以及不规范使用Task.Result 的例子,来加深理解吧!
// Go