10个小技巧助您写出高性能的ASP.NET Core代码

640?wx_fmt=png

今天这篇文章我们来聊一聊如何提升并优化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,原因如下:

  1. 它们阻塞线程直到任务完成,并等待任务完成。等待同步阻塞线程,直到任务完成。

  2. Wait 和 Task.Result 在AggregateException中包含所有类型的异常,并在在执行异常处理时增加复杂性。如果您使用的是等待await 而不是 Task.Wait和Task.Result的话,那么您就不必担心异常的处理了。

  3. 有时,它们都会阻塞当前线程并创建死锁。

  4. 只有在并行任务执行正在进行时才能使用Wait 和Task.Result 。我们建议您不要在异步编程中使用它。

下面让我们分别演示下正确使用以及不建议使用Task.Wait 的例子,来加深理解吧!

// 正确的例子 
Task task = DoWork();
await task;

// 不建议使用的例子
Task task = DoWork();
task.Wait();

下面让我们分别演示下正确使用以及不规范使用Task.Result 的例子,来加深理解吧!

// Good Performance on UI  
Task<string> task = GetEmployeeName();
txtEmployeeName.Text = await task;

// Bad Performance on UI
Task<string> task = GetEmployeeName();
txtEmployeeName.Text = task.Result;

了解更多关于异步编程的最佳实践.


异步执行I/O操作


在执行I/O操作时,您应该异步执行它们,这样就不会影响其他进程。I/O操作意味着对文件执行一些操作,比如上传或检索文件。它可以是任何操作如:图像上传,文件上传或其他任何操作。如果您试图以同步的方式完成它,那么它会阻塞主线程并停止其他后台执行,直到I/O完成为止。因此,从提升性能上来说,您在对I/O进行操作时应该始终进行异步执行。

我们有很多异步方法可用于I/O操作,如ReadAsync、WriteAsync、FlushAysnc等。下面是一个简单的例子,说明我们如何异步创建一个文件的副本。

public async void CreateCopyOfFile()
{
string dir = @"c:\Mukesh\files\";

using (StreamReader objStreamReader= File.OpenText(dir + "test.txt"))
{
using (StreamWriter objStreamWriter= File.CreateText(dir+ "copy_test.txt"))
{
await CopyFileToTarget(objStreamReader, objStreamWriter);
}
}
}

public async Task CopyFileToTarget(StreamReader objStreamReader, StreamWriter objStreamWriter)
{
int num;
char[] buffer = new char[0x1000];

while ((num= await objStreamReader.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await objStreamWriter.WriteAsync(buffer, 0, num);
}
}



总是使用缓存

如果我们能在每次执行的时候减少减少对服务器的请求次数,那么我们就可以提高应用程序的性能。这并不意味着您执行的时候不会请求服务器,而是意味着您不会每次执行都请求服务器。第一次,您将请求服务器并获得响应,此响应将在某个地方存储一段时间(将有一些到期),下一次当您对相同的响应进行调用时,您将首先检查您是否已经在第一个请求中获得了数据并存储在某个地方,如果是的话,您将检查是否已经获得了数据。使用存储的数据,而不是调用服务器。

将数据保存在某个位置并让下次请求从这个地方获取数据而不是从服务器获取是一种很好的做法。在这里,我们可以使用缓存。缓存内容有助于我们再次减少服务器调用,并帮助我们提高应用程序的性能。我们可以在客户端缓存、服务器端缓存或客户机/服务器端缓存等位置的任意点执行缓存。

我们可以在ASP.NET Core中使用不同类型的缓存,比如我们可以在内存中进行缓存,也可以使用响应缓存,也可以使用分布式缓存。更多关于ASP.NET Core 中的缓存

public async Task GetCacheData()
{
var cacheEntry = await
_cache.GetOrCreateAsync(CacheKeys.Entry, entry =>
{
entry.SlidingExpiration = TimeSpan.FromSeconds(120);
return Task.FromResult(DateTime.Now);
});

return View("Cache", cacheEntry);
}

优化数据访问

我们还可以通过优化数据访问逻辑、数据库表和查询来提高应用程序的性能。众所周知,大多数应用程序都使用某种数据库,每次从数据库获取数据时,都会影响应用程序的性能。如果数据库加载缓慢,则整个应用程序将缓慢运行。这里我们有一些建议:

  1. 减少HTTP请求的次数,意味着您应该始终尝试减少网络往返次数。

  2. 试着一次得到所有的数据。这意味着不对服务器进行多次调用,只需进行一两次调用就可以带来所有所需的数据。

  3. 经常对不经常变化的数据设置缓存。

  4. 不要试图提前获取不需要的数据,这会增加响应的负载,并导致应用程序的加载速度变慢。


优化自定义代码

除了业务逻辑和数据访问代码之外,应用程序中可能还有一些自定义代码。确保此代码也是优化的。这里有一些建议:

  1. 应该优化对每个请求执行的自定义日志记录、身份验证或某些自定义处理程序的代码。

  2. 不要在业务逻辑层或中间件中执行长时间运行的代码,它会阻塞到服务器的请求,从而导致应用程序需要很长时间才能获得数据。您应该在客户端或数据库端为此进行优化代码。

  3. 始终检查长期运行的任务是否应该异步执行,而不影响其他进程。

  4. 您可以使用实时客户端-服务器通信框架,如:SignalR,来进行异步工作。


Entity Framework Core 的查询优化

众所周知,EF Core是一个面向.NET开发人员的ORM,它帮助我们处理数据库对象,而不像往常那样编写大量代码。它帮助我们使用模型的数据库。数据访问逻辑代码在性能上起着至关重要的作用。如果您的代码没有优化,那么应用程序的性能通常就不会很好。

但是,如果您在EFCore中以优化的方式编写数据访问逻辑,那么肯定会提高应用程序的性能。在这里,我们有一些技巧来提高性能。

  1. 在获取只是用来只读显示的数据时不使用跟踪。它提高了性能。

  2. 尝试在数据库端过滤数据,不要使用查询获取整个数据,然后在您的末尾进行筛选。您可以使用EF Core中的一些可用功能,可以帮助您在数据库端筛选数据的操作,如:WHERE,Select等。

  3. 使用Take和Skip来获取我们所必须要显示的数量的记录。这里可以举一个分页的例子,在这个例子中,您可以在单击页码的同时使用Take和Skip来获取当前页面的数据。

让我们以一个例子为例,了解如何使用Select和AsNoTracking优化EF Core的查询。

public async Task<PaginatedList> GetPagedPendingPosts(int pageIndex, int pageSize, List allowedCategories)
{
var allowedCatIds = allowedCategories.Select(x => x.Id);
var query = _context.Post
.Include(x => x.Topic.Category)
.Include(x => x.User)
.Where(x => x.Pending == true && allowedCatIds.Contains(x.Topic.Category.Id))
.OrderBy(x => x.DateCreated);

return await PaginatedList.CreateAsync(query.AsNoTracking(), pageIndex, pageSize);
}

其他一些提示

这里我们还有一些其他性能改进的东西可以在ASP.NET Core应用程序中进行实现。

  1. 编写优化和测试代码。您还可以使用来自专业高级开发者的代码示例,包括产品文档。产品团队编写的代码(如C#团队)通常是优化的、现代化的,并且遵循最佳实践。

  2. 使用经过优化和良好测试的API和库。例如,在某些情况下,ADO.NET可能是比 Entity Framework 或其他ORM库更好的选择。

  3. 如果您需要下载一个很大的文件的话,您可能需要考虑使用压缩算法。这里有几个内置的压缩库,如Gzip和Brotli。

public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();

services.Configure(options =>
{
options.Level = CompressionLevel.Fastest;
});
}

附加的建议(面向Client)

我想分享一些面向客户端的提升性能的技巧。如果您正在使用ASP.NET Core MVC创建网站,下面是一些提示:

  • 捆绑和小型化

    使用捆绑和小型化可以减少服务器请求次数。尝试一次加载所有客户端资源,如样式、js/css。您可以首先使用小型化缩小文件,然后将这些文件打包到一个文件中,这将加快加载速度并减少HTTP请求的数量。

  • 最后加载 JavaScript

    您应该始终尝试在页面尾部加载JavaScript文件,除非在此之前需要使用它们。如果您这样做,您的网站将显示的更快,并且用户也不需要等待并看到这些内容。

  • 压缩图像

    确保使用压缩技术缩小图像的大小。

  • 使用 CDN

    如果您只有几个样式和JS文件,那么可以从您的服务器加载。对于较大的静态文件,请尝试使用CDN。CDN通常可以在多个位置上使用,并且文件是从本地服务器提供的。从本地服务器加载文件可以提高网站性能。


最后

今天,我们学习了如何提升ASP.NET Core 应用程序的性能。非常希望这篇文章对你有所帮助,如果您有任何问题或建议,可以在博客下面进行留言或者点赞!最后感谢大伙的阅读,如果你有兴趣的话可以加入ASP.NET Core实战项目交流群637326624跟大伙进行交流,或者加我微信:jkingzhu,备注:合肥,我拉你进入合肥.NET技术社区进行交流!



原文地址:https://www.cnblogs.com/yilezhu/p/10507984.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF 1529D Kavi on Pairing Duty

CF 1529D Kavi on Pairing Duty 题意&#xff1a; 有2 * n个点&#xff0c;现在要求两个点连成线段&#xff0c;每个连法都可以得到n个线段&#xff0c;合法的连接方式为&#xff1a;连接的n个线段&#xff0c;任意两个线段要么长度相等&#xff0c;要么有包含关系 n<1e6 …

东莞.NET技术线下沙龙活动资料分享

今天天气虽然很不好&#xff0c;但不减广大.NET开发者的热情&#xff0c;仍然到场率很高。因图片还在整理中&#xff0c;暂时只发出个简单的活动资料整理分享&#xff0c;后续摄影师图片修图好后&#xff0c;再一并给到场者发送图片&#xff0c;和对活动的现场报道作更详细的图…

对弈(nim-k游戏博弈)

problem AliceAliceAlice 和 BobBobBob 又在玩游戏。 AliceAliceAlice 和 BobBobBob 在一个 1n1\times n1n 的网格图上玩游戏&#xff0c;网格图的 nnn 个格子中&#xff0c;有 kkk 个格子内被各放了一个棋子&#xff0c;其中 kkk 是一个偶数。 从左到右&#xff0c;这 kkk 个…

.Netcore 2.0 Ocelot Api网关教程(6)- 配置管理

本文介绍Ocelot中的配置管理&#xff0c;配置管理允许在Api网关运行时动态通过Http Api查看/修改当前配置。由于该功能权限很高&#xff0c;所以需要授权才能进行相关操作。有两种方式来认证&#xff0c;外部Identity Server或内部Identity Server。1、外部Identity Server修改…

最短路径(虚树+期望)

problem 给定一棵 nnn 个结点的无根树&#xff0c;每条边的边权均为 111 。 树上标记有 mmm 个互不相同的关键点&#xff0c;小 A 会在这 mmm 个点中等概率随机地选择 kkk 个不同的点放上小饼干。 你想知道&#xff0c;经过有小饼干的 kkk 个点的最短路径长度的期望是多少。…

【学习笔记】最大权闭合子图和最大密度子图(最小割的模型应用)

最大权闭合子图和最大密度子图最大权闭合子图contentexercise最大密度子图contentexerciseUpd&#xff1a;最大权闭合子图易懂证明最大权闭合子图 content 先作出以下声明&#xff1a; c(u,v):c(u,v):c(u,v): 边 (u,v)(u,v)(u,v) 的容量。 f(u,v):f(u,v):f(u,v): 边 (u,v)(u,…

Docker最全教程之使用Docker搭建Java开发环境(十八)

前言Java是一门面向对象的优秀编程语言&#xff0c;市场占有率极高&#xff0c;但是在容器化实践过程中&#xff0c;发现官方支持并不友好&#xff0c;同时与其他编程语言的基础镜像相比&#xff08;具体见各语言镜像比较&#xff09;&#xff0c;确实是非常臃肿。本篇仅作探索…

AT2705 [AGC019F] Yes or No(组合数学)

解析 Atcoder的题超小的码量总让人做不出来的时候感到很不甘心… 但这题确实挺难的&#xff0c;主要还是魔术一样的奇淫技巧。 大力推式子那个阴间方法我直接选择弃疗。 一个很显然的结论是&#xff1a;肯定回答当前剩的比较多的选项。 pia一张洛谷的图&#xff1a; &#…

ASP.NET Core 项目简单实现身份验证及鉴权

环境VS 2017ASP.NET Core 2.2目标以相对简单优雅的方式实现用户身份验证和鉴权&#xff0c;解决以下两个问题&#xff1a;无状态的身份验证服务&#xff0c;使用请求头附加访问令牌&#xff0c;几乎适用于手机、网页、桌面应用等所有客户端基于功能点的权限访问控制&#xff0c…

ML.NET 发布0.11版本:.NET中的机器学习,为TensorFlow和ONNX添加了新功能

微软发布了其最新版本的机器学习框架&#xff1a;ML.NET 0.11带来了新功能和突破性变化。新版本的机器学习开源框架为TensorFlow和ONNX添加了新功能&#xff0c;但也包括一些重大变化, 这也是发布RC版本之前的最后一个预览版&#xff0c;这个月底将发布0.12版本&#xff0c;也就…

如何使用AWS和Azure的配置存储服务保存读取配置

原文&#xff1a;Want to yank configuration values from your .NET Core apps? 作者&#xff1a;pauljwheeler译文&#xff1a;https://www.cnblogs.com/lwqlun/p/10508748.html译者&#xff1a;Lamond Lu示例源代码&#xff1a;https://github.com/lamondlu/LoadConfigurat…

Meaningless Sequence Gym - 102832D

Meaningless Sequence Gym - 102832D 题意&#xff1a; 给你n和c&#xff0c;an的公式如下图 让你求a0…an的和&#xff0c;mod 1e97 题解&#xff1a; 训练时推了好一阵子才和队友推出 我看网上正解为&#xff1a; 一个数的大小与它的二进制表示中的1的个数有关 ac(二进制…

【.NET Core项目实战-统一认证平台】第十六章 网关篇-Ocelot集成RPC服务

一、什么是RPCRPC是“远程调用&#xff08;Remote Procedure Call&#xff09;”的一个名称的缩写&#xff0c;并不是任何规范化的协议&#xff0c;也不是大众都认知的协议标准&#xff0c;我们更多时候使用时都是创建的自定义化&#xff08;例如Socket&#xff0c;Netty&#…

.net Core2.2 WebApi通过OAuth2.0实现微信登录

前言微信相关配置请参考 微信公众平台 的这篇文章。注意授权回调域名一定要修改正确。微信网页授权是通过OAuth2.0机制实现的&#xff0c;所以我们可以使用 https://github.com/china-live/QQConnect 这个开源项目提供的中间件来实现微信第三方登录的流程。开发流程1、新建一个…

Nginx优化(重点)与防盗链(新版)

Nginx优化(重点)与防盗链 Nginx优化(重点)与防盗链一、隐藏Nginx版本号1、修改配置文件2、修改源代码 二、修改Nginx用户与组1、编译安装时指定用户与组2、修改配置文件指定用户与组 三、配置Nginx网页的缓存时间四、实现Nginx的日志切割1、data的用法2、编写脚本进行日志切割的…

CodeForces730E Award Ceremony(拓扑排序+结论)

CF730E. Award Ceremonyproblemsolutioncodeproblem 题目链接 题目大意&#xff1a; 给出 nnn 个队封榜时的榜单 aia_iai​ 和揭榜时的变化情况 did_idi​。 揭榜时&#xff0c;这个队的名次会变化 tit_iti​。 注意在别的队揭榜时&#xff0c;自己队的排名也是动态变化的…

.Netcore 2.0 Ocelot Api网关教程(番外篇)- Ocelot v13.x升级

由于Ocelot系列博客好久没更新&#xff08;差不多有10个月的时间了&#xff09;&#xff0c;在此先说声抱歉&#xff0c;Ocelot系列会继续更新下去。在写上一篇配置管理的时候发现官方文档已经和以前的不一样&#xff0c;而Ocelot也从5.0版本更新到了13.x版本&#xff0c;进行了…

CF765F Souvenirs(暴力、线段树)

解析 比较神奇的一道题。 考虑一个常规套路&#xff1a;把询问离线&#xff0c;移动右端点&#xff0c;维护左端点答案。 考虑暴力维护&#xff0c;对于当前的 aixa_ixai​x&#xff0c;左侧如图所示的这两条线上的点都可以产生新的可能答案。 容易构造使得单次产生的新点是…

Hard Disk Drive HDU - 4788

Hard Disk Drive HDU - 4788 题意&#xff1a; 通常制造商认为1“kilo”等于1000&#xff0c;但操作系统会认为是1024。 因此&#xff0c;当你购买了一个100MB的硬盘&#xff0c;电脑却只显示大约有95MB&#xff0c;这缺失了大约5MB。 对于硬盘的大小&#xff0c;有多种单位描…

ASP.NET Core 沉思录 - 环境的思考

我的博客换新家啦&#xff0c;新的地址为&#xff1a;https://clrdaily.com :-D今天我们来一起思考一下如何在不同的环境应用不同的配置。这里的配置不仅仅指 IConfiguration 还包含 IWebHostBuilder 的创建过程和 Startup 的初始化过程。0 太长不读环境造成的差异在架构中基本…