今天這篇文章咱們來聊一聊如何提高並優化ASP.NET Core應用程序的性能,本文的大部份內容來自翻譯,固然中間穿插着本身的理解,但願對你們有所幫助!話很少說開始今天的主題吧!
咱們都知道性能是公共網站取得成功的關鍵因素之一。若是一個網站的響應時間超過3秒,那麼用戶一般不會再此光顧(此網站)。谷歌,Bing,百度以及其餘搜索引擎也更傾向於推薦優化後的,移動友好的以及響應速度更快的網站。css
做者:依樂祝html
原文地址: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網站性能的一些小技巧。但願你們可以有所收穫。c#
咱們都知道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的第一個版本是在2016年與VisualStudio 2015一塊兒發佈的,如今咱們有了ASP.NET Core3.0,每個新版本都愈來愈好。最新的ASP.NET Core 3.0的主要更新以下:網絡
友情提示:在構建新的ASP.NET Core項目時,不要忘記選擇最新版本。VisualStudio 2019預覽版如今已經支持ASP.NET Core 3.0了。
在開發ASP.NET Core應用程序時,儘可能避免建立阻塞的調用。阻塞調用是指當前請求未完成以前會一直阻止下一個執行的調用。阻塞調用或同步調用能夠是任何東西,能夠是從API中獲取數據,也能夠是執行一些內部操做。您應該始終以異步方式執行調用。
異步編程模型是在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和Task.Result並嘗試使用WAIT,緣由以下:
下面讓咱們分別演示下正確使用以及不建議使用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操做,如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); }
咱們還能夠經過優化數據訪問邏輯、數據庫表和查詢來提升應用程序的性能。衆所周知,大多數應用程序都使用某種數據庫,每次從數據庫獲取數據時,都會影響應用程序的性能。若是數據庫加載緩慢,則整個應用程序將緩慢運行。這裏咱們有一些建議:
除了業務邏輯和數據訪問代碼以外,應用程序中可能還有一些自定義代碼。確保此代碼也是優化的。這裏有一些建議:
衆所周知,EF Core是一個面向.NET開發人員的ORM,它幫助咱們處理數據庫對象,而不像往常那樣編寫大量代碼。它幫助咱們使用模型的數據庫。數據訪問邏輯代碼在性能上起着相當重要的做用。若是您的代碼沒有優化,那麼應用程序的性能一般就不會很好。
可是,若是您在EFCore中以優化的方式編寫數據訪問邏輯,那麼確定會提升應用程序的性能。在這裏,咱們有一些技巧來提升性能。
在獲取只是用來只讀顯示的數據時不使用跟蹤。它提升了性能。
嘗試在數據庫端過濾數據,不要使用查詢獲取整個數據,而後在您的末尾進行篩選。您可使用EF Core中的一些可用功能,能夠幫助您在數據庫端篩選數據的操做,如:WHERE,Select等。
使用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應用程序中進行實現。
編寫優化和測試代碼。您還可使用來自專業高級開發者的代碼示例,包括產品文檔。產品團隊編寫的代碼(如C#團隊)一般是優化的、現代化的,而且遵循最佳實踐。
使用通過優化和良好測試的API和庫。例如,在某些狀況下,ADO.NET多是比 Entity Framework 或其餘ORM庫更好的選擇。
若是您須要下載一個很大的文件的話,您可能須要考慮使用壓縮算法。這裏有幾個內置的壓縮庫,如Gzip和Brotli。
public void ConfigureServices(IServiceCollection services) { services.AddResponseCompression(); services.Configure(options => { options.Level = CompressionLevel.Fastest; }); }
我想分享一些面向客戶端的提高性能的技巧。若是您正在使用ASP.NET Core MVC建立網站,下面是一些提示:
捆綁和小型化
使用捆綁和小型化能夠減小服務器請求次數。嘗試一次加載全部客戶端資源,如樣式、js/css。您能夠首先使用小型化縮小文件,而後將這些文件打包到一個文件中,這將加快加載速度並減小HTTP請求的數量。
最後加載 JavaScript
您應該始終嘗試在頁面尾部加載JavaScript文件,除非在此以前須要使用它們。若是您這樣作,您的網站將顯示的更快,而且用戶也不須要等待並看到這些內容。
壓縮圖像
確保使用壓縮技術縮小圖像的大小。
使用 CDN
若是您只有幾個樣式和JS文件,那麼能夠從您的服務器加載。對於較大的靜態文件,請嘗試使用CDN。CDN一般能夠在多個位置上使用,而且文件是從本地服務器提供的。從本地服務器加載文件能夠提升網站性能。
今天,咱們學習瞭如何提高ASP.NET Core 應用程序的性能。很是但願這篇文章對你有所幫助,若是您有任何問題或建議,能夠在博客下面進行留言或者點贊!最後感謝大夥的閱讀,若是你有興趣的話能夠加入ASP.NET Core實戰項目交流羣跟大夥進行交流,或者加我微信:jkingzhu,備註:合肥,我拉你進入合肥.NET技術社區進行交流!