2023-02-09|閱讀時間 ‧ 約 8 分鐘

Fast Endpoints 一個基於 REPR 設計模式的 .NET 輕量高性能 API 框架

fast endpoints 是一個支援 .NET 6 以上(Nuget 版本清單) 的 API 輕量框架,雖以簡單與高性能為主打,但也提供了很多常用的功能實現,如 Swagger 整合、Jwt 認證、Api 版本控制、APi 速率限制、Api 回應快取…很適合以此為基礎打造 Api 服務。

為什麼選用 Fast Endpoints

Fast Endpoints 有一個很大的優勢在於他的效能與功能使用上的彈性,相較於大部分的開發框架由於要實現較為完善的功能而犧牲了部分的效能與開發上彈性,Fast Endpoints 採用最小化的引入門檻,大部分資源都透過引用 Fast Endpoints Nuget 套件來依照需求引用,如 FastEndpoints.SwaggerFastEndpoints.SecurityFastEndpoints.ClientGen…等,依照需求引用配置。
採用了 REPR Design Pattern 的設計,將 Api 拆解成 Request(請求)、Endpoint(端點)、Response(回應),用這樣的方式來處理 Api 的生命週期與資料處理的模型,這樣單純的模式有助於讓我們專注在更單純的 Request、Response 而不是大量的 ViewModel 轉換或是貧血的 Controller 層。

性能

官方做了幾項測試 ,使用到了 bombardierTechEmpower 這兩套知名的性能測試工具。
詳細數據可以到官方提供的 Benchmarks 中查看,這裡只做簡單的小結論
Fast Endpoints 不是每秒能回應最多請求的,與 ASP NET Minimal API 相比仍然是差了一點,但差距不到明顯,考慮到額外能提供的 Swagger 支援與權限控管的機制,仍然是不算虧。
Fast Endpoints 比 ASP NET MVC Controller 多處理了約 35k 個請求,猜測 MVC 架構有較多的轉換與 middleware 層做事,在沒有業務邏輯的情況下稍慢是合理。
雖然官方做了這些測試,但其實我個人不會太以這標準來做技術選型,我認為現代框架重要的是人的開發效率、高可用性與彈性,如何做到架構好改好測試會是比較重要的問題,況且這是在沒有業務邏輯的單純狀況下做測試,很多時候拖累的不是框架本身,而是沒有最佳化的演算法導致程式做了白工,所以這個參考就好。

開始使用

Fast Endpoints 有提供 FastEndpoints.Template 這個啟動範本,可以直接安裝使用,也有提供很多可以直接使用的模板在 scaffolding 可以依據需求選用。
安裝 FastEndpoints.Template 範本,並且使用 [PROJECT-NAME] 啟動專案。
dotnet new --install FastEndpoints.Template
dotnet new fastendpoints --name [PROJECT-NAME]
但我們這裡以最具彈性的方式來做示範,開發一個簡易的 API Api 的目的為輸入會員的資料,判斷該會員是不是 Premium 高級會員。
API 的規格會有
  1. Request = totalSpend(會員的累積消費金額)
  2. Endpoint = get_member_is_Premium(得到該玩家是否為 Premium 高級會員)
  3. Response = isPremium(是否為 Premium 高級會員)
  4. Logic = 當累積消費金額大於等於 100000 時就算是 Premium 高級會員
所以第一步我們先建一個空白的專案 (目前是使用 .NET 6 作為示範),並且安裝好 FastEndpoints。
dotnet new web -n fastEndpointsDemoApi
cd fastEndpointsDemoApi
dotnet add package FastEndpoints
我們先將 Program.cs 用以下程式碼覆蓋,主要做的更動是將 FastEndpoints 作為全局的引入套件,在每一個檔案中都會預設 using FastEndpoints 而不需額外指定。
global using FastEndpoints;

var builder = WebApplication.CreateBuilder();
builder.Services.AddFastEndpoints();

var app = builder.Build();
app.UseAuthorization();
app.UseFastEndpoints();
app.Run();
再接下來的資料夾結構可以依據開發的程式類型或習慣來設計,我這裡習慣是建立一個 Endpoints 的資料夾,並在裡面放置其定義的資料模型與功能
我們先來定義 Models
namespace fastEndpointsDemoApi.Endpoints.GetMemberIsPremium;

public class Request
{
   public decimal TotalSpend { get; set; }
}

public class Response
{
   public bool IsPremium { get; set; }
}
再來定義 Endpoint
namespace fastEndpointsDemoApi.Endpoints.GetMemberIsPremium;

public class Endpoint : Endpoint<Request>
{
   public override void Configure()
   {
       Get("/get_member_is_premium");
       AllowAnonymous();
   }

   public override async Task HandleAsync(Request req, CancellationToken ct)
   {
       var response = new Response
       {
           IsPremium =  req.TotalSpend >= 100000
       };

       await SendAsync(response, cancellation: ct);
   }
}
我們現在已經完成了一個 端點為 get_member_is_premium 並且可以透過輸入已經儲值的金額判斷是否為 premium 的 API 了,我們馬上來試一下
找不到很正常,因為我們根目錄的確沒寫東西
100 尚未達到 premium 的門檻
我們來測一下 100000
100000 達到 premium 的門檻,所以回傳了 true
至此我們完成了一個簡易的 API,沒有呼叫資料庫所以基本上不會是很常見的 API 型式,我們把這命名為 NoDatabaseApi ,完整的程式碼可以在 這裡 找到,而目前階段的程式碼可以在 add NoDatabaseApi 這個 commit 記錄裡找到
後續的篇章會實現透過 Dapper 與 PostgreSQL 互動的功能
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.