ASP.NET Core API & Blazor 實作快取機制提升效能


January 8, 2024 程式語言

ASP.NET Core API & Blazor 實作快取機制提升效能


何謂快取? 快取機制基本介紹與紀錄如何使用 ASP.NET Core API 實作快取機制。

前言

🔗

最近的專案,因為有大量縮圖與計算,導致每次畫面呈現的速度,都達不到想要的水準,除了本身代碼與 T-SQL 的優化、還可以藉由懶加載 ( Lazy loading ) 等,達到提升資料讀取速度的效果。

除了這些方式,還能藉由快取,達到更好的性能,此文章紀錄使用 Blazor WASM 架構與 ASP.NET Core API 建立快取機制。

快取機制

🔗

說到快取(緩存),可以理解為使用或是讀取預先存放好的資料,因為不用重新從資料庫或是伺服器取得檔案,速度可以有效提升,降低網站負荷。

如果網站為靜態網站,或是有大量靜態資源的需求,若每次使用者進入網站,都需要讀取一次資源,那勢必會有流暢度的問題,這時若使用 CDN(Content Delivery Network)服務,藉由分布於全球的伺服器節點組成的網路,就能有效提升靜態資源的傳輸速度與性能,這其中就有用到快取的技術,藉由預先存放靜態資源在各地,達到高效傳輸。

而若是在後端 API 的部分,也能使用類似的快取機制達到高效傳輸,預先存放資料的位置則是存放在記憶體中。本篇將介紹如何使用 MemoryCache 類進行緩存,若是大型網站或是分散式系統可使用 IDistributedCache 類等之後有機會再研究。

使用時機

🔗

若要使用 MemoryCache 類進行緩存,因資料存放於記憶體,若應用程式關閉或重啟、系統故障,或是系統本身對於內存進行管理與優化,都會造成存放的資料消失。所以快取並不建議存放重要資料,或是頻繁變動的資料以致網站內容資訊不正確。

以本篇為例,專案網站在首頁會顯示封面圖,而因為封面圖並不會頻繁更新,且資料也已儲存在資料庫與AWS S3,所以預先儲存在快取,就是一個不錯的方式以提升使用者載入首頁的速度。

代碼

🔗

建立快取

🔗

架構不管是 Blazor WASM 還是 一般的 Web API 都是對控制器內的 API 進行修改。 代碼如下:

C#
using Microsoft.Extensions.Caching.Memory;
namespace BlazorApp.Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StorageController : ControllerBase
    {
        private readonly IStorageService _storageService;
        private readonly IMemoryCache _cache;

        public StorageController(IStorageService storageService, IMemoryCache memoryCache)
        {
            _storageService = storageService;
            _cache = memoryCache;
        }

        [HttpGet("logo/admin-no-cache")]
        public async Task<List<S3FileInfo>> GetLogoFileNoCache()
        {
            List<S3FileInfo> FileInfo = await _storageService.GetFileByKeyAsync();
            return FileInfo;
        }

        [HttpGet("logo")]
        public async Task<List<S3FileInfo>> GetLogoFile()
        {
            string cacheKey = "logo";
            if (!_cache.TryGetValue<List<S3FileInfo>>(cacheKey, out List<S3FileInfo> cachedData))
            {
                List<S3FileInfo> FileInfo = await _storageService.GetFileByKeyAsync();
                cachedData = FileInfo;

                _cache.Set(cacheKey, cachedData, TimeSpan.FromHours(24));
            }
            return cachedData;
        }
    }
}

有兩支 API,一支為logo/admin-no-cache為管理員使用,針對管理員需當下確認資料正確性,為無快取版本。

另一支為logo,供首頁載入時使用,邏輯為設定快取的Key為logo,每次呼叫時,需確認快取是否有包含Key為logo的資料, 若有則取用,若無則重新取得資料。

_cache.Set(cacheKey, cachedData, TimeSpan.FromHours(24));
在取得資料後,儲存資料至快取,並設定24小時候過期。也就是說每過了24小時,快取就會消失,之後的第一個讀取網站的人,載入速度就會回歸正常,因為必須重新讀取資料,而之後的每位使用者就還是一樣的高效快速。😎

移除快取

🔗

有時也有清除快取的需求,例如資料更新後清除快取以讓使用者看到即時內容。
移除特定快取代碼:

C#
_cache.Remove("logo");

取得快取列表

🔗

網站有快取之後,為了部分即時更新的資料還是得提供管理者清除快取功能,可以藉由取得目前記憶體儲存的快取 key 列表後,再配合上方移除快取進一步刪除。

C#
[HttpGet("cache")]
public async Task<List<string>> GetCacheList()
{
    var field = typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance);
    var collection = field.GetValue(_cache) as ICollection;
    var items = new List<string>();
    if (collection != null)
        foreach (var item in collection)
        {
            var methodInfo = item.GetType().GetProperty("Key");
            var val = methodInfo.GetValue(item);
            items.Add(val.ToString());
        }
    return items;
}

結論

🔗

以上就是如何使用 ASP.NET Core 實作內存快取機制,個人是把需要快取的資料分為兩支 API,比較好分類,實際可依照需求增加判斷決定是否取得快取資料或是實際資料。網站若是使用雲端資料庫或是 S3 等服務,如果能好好善用快取,相信可以減少許多傳輸資料的花費呢。😎

CsharpBlazorWeb



Avatar

Alvin

軟體工程師,喜歡金融知識、健康觀念、心理哲學、自助旅遊與系統設計。

相關文章






留言區 (0)



  or   

尚無留言