天天看點

使用 YARP 和 .Net 在 C# 中建構 API 網關

作者:opendotnet
使用 YARP 和 .Net 在 C# 中建構 API 網關

第一章 入門

當我們在平台中使用許多應用程式時,我們有許多配置,這些應用程式可能需要互相通信。在社群中,我們有一些模式可以解決這種情況,其中之一就是 API Gateway 模式。此解決方案位于用戶端和應用程式之間,它負責路由請求的應用程式的請求、對請求進行身份驗證和授權以及許多其他功能。

現在我們有很多API網關解決方案,比如Kong、KrakenD、Tyk和Apache APISIX,這些解決方案可以是開源的,也可以是授權的,每個都有自己的特點。在本文中,我們選擇 YARP 是出于某些原因,這些原因是熟悉開發的代碼語言,并且它是由 Microsoft 維護的開源庫。

我們打算像一系列文章一樣維護這一點,這些文章描述了使用 .Net 和 YARP 實作 api 網關的過程,并具有一些重要功能,如防火牆、速率限制、功能标志、身份驗證等。

要開始這個項目,我們需要安裝 dotnet 8 和 docker。

要開始我們的開發,我們要做的第一步是建立一個簡單的應用程式來測試我們的路由和我們功能的适用性。

dotnet new web -o RoutingTestAPI
           

現在,在生成的程式檔案中,我們将添加一些環境變量,以幫助我們可視化測試時的一些情況:

var defaultPath = Environment.GetEnvironmentVariable("ROOT_PATH"); 
var destination = Environment.GetEnvironmentVariable("DESTINATION"); 
var app = Environment.GetEnvironmentVariable("APP_NAME");
           

為了完成我們的代碼,我們将添加一個端點來傳回我們在路由請求時可以看到的内容:

app.MapGet($"{defaultPath}/simulate", () => $"Successfull request for destination {destination} from {app} app\n");
           

至此,我們完成了最小路由 API,使我們能夠測試我們的 API 網關。現在,為了更友善起見,我們将使用此路由 API 建立一個 docker compose 檔案,我們将能夠根據需要複制和操作部署,但首先我們需要釋出此 API:

dotnet publish --os linux --arch arm64 -p:PublishProfile=DefaultContainer
           

如果您在 Windows 或 Linux 中運作此代碼,請删除 arch 指令。此指令将在 docker 守護程式中釋出 docker 映像

之後,我們可以建立具有以下規範的 docker compose 檔案:

services:
 fooapp:
 image: simple-routing-app:latest
 restart: always
 environment:
 - ROOT_PATH=/api/foo
 - APP_NAME=foo
 - DESTINATION=destination1
 ports:
 - 8080:80
           

現在我們可以開始建構我們的 API 網關了,首先我們需要建立另一個 dotnet API 并将 YARP 庫添加到這個 API:

dotnet new web -o Gateway 
dotnet add package Yarp.ReverseProxy
           

要在我們的項目中配置反向代理,我們需要在配置中添加以下服務:

public void ConfigureServices(IServiceCollection services) 
{ 
 services.AddReverseProxy(); 
} 
public void Configure(IApplicationBuilder app) 
{ 
 app.UseRouting(); 
 app.UseEndpoints(); 
}
           

現在我們需要添加一些路由配置,為此我們有很多選擇:

  1. 将名為 ReverseProxy 的配置添加到我們的appsettings.json
  2. 建立 InMemoryConfigProvider
  3. 建立自定義 IProxyConfigProvider

我們将選擇第三種方式,因為這将是下一章的鈎子,以及我們希望如何最接近真實情況,對我來說,這是最好的方法。

為此,我們需要建立一個名為“CustomProxyConfigProvider”的新類,該類需要擴充接口 IProxyConfigProvider,該接口實作了 GetConfig() 方法和擴充 IProxyConfig 的“CustomMemoryConfig”類。

public class CustomProxyConfigProvider: IProxyConfigProvider
{
private CustomMemoryConfig _config;

public IProxyConfig GetConfig() => _config;
}

public class CustomMemoryConfig: IProxyConfig
{
private readonly CancellationTokenSource _cts = new CancellationTokenSource();

public CustomMemoryConfig(IReadOnlyList<RouteConfig> routes, IReadOnlyList<ClusterConfig> clusters)
 {
 Routes = routes;
 Clusters = clusters;
 ChangeToken = new CancellationChangeToken(_cts.Token);
 }

public IReadOnlyList<RouteConfig> Routes { get; }
public IReadOnlyList<ClusterConfig> Clusters { get; }
public IChangeToken ChangeToken { get; }

internal void SignalChange()
 {
 _cts.Cancel();
 }
}
           

為了将請求路由到我們的應用程式,我們需要向我們的 API Gateway 提供一些配置,YARP 使用由路由和叢集組成的标準配置,我們将在 CustomProxyConfigProvider 中建立一個方法來建立此配置:

public void LoadConfig() 
{
var routeConfig = new RouteConfig 
 { 
 RouteId = "route1",
 ClusterId = "cluster1", 
 Match = new RouteMatch
 {
 Path = "/api/foo/{**catch-all}"
 }
 };
var clusterConfig = new ClusterConfig
 {
 ClusterId = "cluster1",
 LoadBalancingPolicy = LoadBalancingPolicy.RoundRobin,
 Destinations = new Dictionary<string, DestinationConfig>()
 {
"destination1", new DestinationConfig
 {
 Address = "http://localhost:8080"
 }
 }
 }

var routes = new List<RouteConfig>();
 routes.add(routeConfig);
var clusters = new List<ClusterConfig>();
 clusters.add(clusterConfig);

 _config = new CustomMemoryConfig(routes, clusters);
}
           

我們需要将此提供程式添加到 Startup 類的配置中:

public void ConfigureServices(IServiceCollection services) 
{ 
 services 
 .AddSingleton<IProxyConfigProvider>(new CustomProxyConfigProvider()) 
 .AddReverseProxy(); 
}
           

通過此配置,我們可以運作應用程式并測試網關的路由,是以首先,我們将運作本文開頭建立的 docker compose:

docker compose up -d
           

并運作我們的 Gateway 項目:

dotnet run .
           

現在,我們已經運作了應用程式和已配置的 API 網關,我們可以調用來測試路由,當我運作網關時,請選擇要公開的端口 5025:

curl http://localhost:5025/api/foo/simulate
           

這将響應以下消息:

Successfull request for destination destination1 from foo app
           

在本章的最後,我們建立了一個簡單的應用程式,并對我們的網關進行了簡單的配置,并檢視通過我們的 API 網關路由的請求。在下一章中,我們将建立控制平面,使我們的配置能夠在運作時更改并自定義我們的配置。

如果你喜歡我的文章,請給我一個贊!謝謝

繼續閱讀