🚪

Ocelot を C# で動かしながら API ゲートウェイを理解する

2025/02/26に公開

API ゲートウェイとは

API ゲートウェイは、API リクエストの手前に配置して通信をとりまとめることで、各種サービスとのやり取りをより簡単にするものです。

API ゲートウェイの簡単な図

特に業務単位などでサービスを分割したマイクロサービスを構築する場合に威力を発揮します。

もちろん、ブラウザなどから直接各種サービスにアクセスすることも可能ですが、例えば以下のような問題があります。

  • 各種サービスへのリクエストの順番や渡すパラメータを呼び出し側が詳しく知る必要がある
  • バックエンドの変更があると、呼び出し側の変更が必要になる可能性がある
  • 一度に多くの関連データを取得するとネットワークのレイテンシが大きくなる

API ゲートウェイを使用すると上記を解決するだけでなく、以下のようなメリットもあります。

  • リクエストのロギング集約
  • キャッシュやレート制限などの設定を一元管理
  • サーキットブレーカーの使用
    • リクエストが一定数連続で失敗した場合など、呼び出し先の障害を検知した場合にリクエストを停止する仕組みのこと

もちろん管理・開発するものが1つ増えるわけなので多少の手間は増えますが、規模が大きくなればなるほど、より導入の効果を大きく感じるものになります。

Ocelot で API ゲートウェイを実装してみる

今回は Ocelot という OSS を使用して、非常にシンプルな API ゲートウェイを作成して動かしてみました。
https://github.com/ThreeMammals/Ocelot

作成した全体像は以下のとおりです。

  • 最初の実行は http ファイルから
  • API ゲートウェイに Ocelot を使用
  • 呼び出し先はテンプレに入っている WeatherForecast をそのまま使用

本来であれば呼び出し先が複数になったり、認証/認可のサーバーも用意が必要だったりと、もう少し複雑になるはずです。

たくさんの機能が用意されているので、より詳しく知りたい方は公式ドキュメントも参照してください。
https://ocelot.readthedocs.io/en/latest/index.html

簡単な内容ですが今回試した内容はコードも公開しています。
https://github.com/nekojoker/OcelotSample

Ocelot の導入

Ocelot を使用するには、NuGet パッケージの追加が必要です。

ocelot.json を追加します。

ocelot.json
{
  "Routes": [
    {
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5092
        }
      ],
      "DownstreamPathTemplate": "/weatherforecast",
      "DownstreamScheme": "http",
      "UpstreamPathTemplate": "/gateway/weather",
      "UpstreamHttpMethod": [ "Get" ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "https://localhost:5204"
  }
}

Downstream は宛先サーバーのことで、今回でいうと WeatherForecast です。
Upstream は GW のことで、今回でいうと Ocelot です。

つまり、以下の内容を設定しています。

  1. クライアントからは localhost:5204/gateway/weather の GET で受け付ける
  2. GW からlocalhost:5092/weatherforecast の GET をリクエストする

続いて、Program.cs に Ocelot を使用する記述を追加します。
app.UseOcelot() の戻り値が Task のため、await をつけることができます。

Program.cs
using Ocelot.DependencyInjection;
using Ocelot.Middleware;

var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
builder.Services.AddOcelot(builder.Configuration);
var app = builder.Build();

app.UseHttpsRedirection();
await app.UseOcelot();

app.Run();

最後に、GW に対してリクエストする http ファイルを作成すれば準備完了です。

@ApiGateway_HostAddress = http://localhost:5204

GET {{ApiGateway_HostAddress}}/gateway/weather
Accept: application/json

実際に http ファイルを動かしてみると、GW に対してリクエストを送った結果、WeatherForecast からデータが返却されていることが確認できました。


GW を経由してデータが取得できた図

BFF パターンとは

API クライアントとしては主に、Web やモバイルアプリ、サードパーティが挙げられます。
GW がひとつだと、以下のような問題が発生する場合があります。

  • 1 つの API に問題が発生すると、Web 向けだけでなく他のクライアントにも影響が出る
  • すべてのクライアントの API が含まれるため、どんどん規模が大きくなる

BFF(Backends for frontends)パターンは、クライアントの種類ごとに GW を分割する方法です。
このようにすると、先ほど挙げた問題を解消できます。

BFF パターンの簡単な図

API ゲートウェイのクラウドサービス

OSS を使ってセルフホストするのも大変なので、クラウドサービスを利用するのもよいです。
基本的には、サーバーのホスト先と同じ環境で使えるものがあれば、それを使用するのが一般的だと思います。

最後に

Ocelot を C# で動かしつつ API ゲートウェイについて解説してみました。

マイクロサービスをちゃんと作るには結構大変だなという印象です。

引き続きマイクロサービス関連の知識をインプットして、何か学びがあればまたアウトプットしてみたいと思います。

参考文献

Discussion