【2023年版】分散GraphQLの動向~Fusionを中心に~

# はじめに
GraphQLConf 2023が2023/9/19-21で開催されていました。

https://graphql.org/conf/

そこで個人的に特に気になったのが**Open Federation**や**Fusion**といったGatewayの仕様周りの話題です。

これら2つは何が異なるのか、Apollo Federationと何が異なるのか、それらを実装したサーバにはどんなものがあるのか、等いくつか気になることがあったので、講演と自身で調べた内容を併せて紹介したいと思います。

ちなみにGraphQLConfはアーカイブをYoutubeで公開しているので興味ある方はぜひ。

https://www.youtube.com/playlist?list=PLP1igyLx8foE9SlDLI1Vtlshcon5r1jMJ

# 想定読者

- GraphQL Gatewayの歴史を知りたい方
- GraphQL Gatewayについての知見を深めたい方
- Open FederationとFusionの違いを知りたい方

# GatewayとしてのGraphQLの歴史
元々はFaceBookでは以下のようなモノリシックなアプリケーションでGraphQLが活用されていたようです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636552/7366f99e-577e-d876-7f00-3b3e95d29d30.png" width=100%>

それがオープンソースとして公開されると、既存システムへの影響を考慮した結果既存構成のままREST APIをGraphQLでラップし以下のようなGatewayとして利用されました。これによってクライアント側でデータを集約することがなくなり、優れた開発者体験とパフォーマンスを実現しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636552/f550bd5b-fed7-a678-e499-94e22095ad85.png" width=100%>

このような分散GraphQLは開発規模のスケーリングのために行います。
複数チームで開発する場合のアプローチとしてモジュラーモノリスがありますが、多くのチームで開発している大規模アプリケーションの場合、競合のある更新が多く発生します。分散GraphQLであればサブグラフについて各チームが責任を持つことができ、更新の競合が起きないため開発規模のスケーリングに向いています。

分散GraphQLを実現する方法として以下があります。
- Atlassian Nadel
- Schema Stiching
- GraphQL Mesh
- Apollo Federation

これらの共通点は、**オープンスタンダードではない**ということです。
そしてこれが分散GraphQLを実現するGraphQL Gateway界隈の課題です。
オープンな仕様がないので実際にはベンダーロックインされてしまうのです。

こういった背景から**Open Federation**や**Fusion**のようなオープンスタンダードを定義する仕様策定が始まっています。

**Open Federation**と**Fusion**はそれぞれどんな仕様を決めるもので何が違うのか比較していきたいと思います。

# Open FederationとFusionの比較
## Open Federation
[Open Federation](https://open-federation.org/)はバックエンドサービス(GraphQL API)のFederationを実現するためのオープンな仕様です。Apollo Federationをベースにしており、方針レベルではApollo Federationから容易に移行できるよう常に最新バージョンのApollo Federationとの互換性を保つことを目標としているみたいです。
WunderGraphとThe Guildが中心となって仕様策定を進めています。
仕様書は以下にあります。2023/12/11時点では2023/9/27公開のWorking Draftのみ公開されています。

https://spec.open-federation.org/

2023/12/11時点ではほとんど目次くらいしか書かれておらず、Composition セクションのみ中身が少し書かれているくらいの状況です。
大体以下の内容が定義されるみたいです。

- Subgraph Specificationの再定義
- Federated Graphのコアコンセプトの定義
- Subgraph composition checksを実装するための検証ルールの定義
- SubgraphスキーマからFederatedスキーマを生成するための合成アルゴリズムの定義
- Federated GraphQL Operations を実行するために Router が実装するコア実行アルゴリズムの定義

ちなみにGraphQLConf 2023ではThe Guildの[Uri Goldshtein](https://github.com/Urigo)さんの講演で触れられていますが、ここでも中身の説明はほとんどありませんでした。

## Fusion
Fusionは様々な規格のバックエンドサービス(GraphQL APIに限らずRESTやgRPCなど)のFederationを実現するためのオープンな仕様です。ChilliCreamとThe Guildが中心となって、Hasura、IBM、solo.io、AWS AppSync、WunderGraphが仕様策定を進めています。
仕様書は2023/12/11時点ではまだ公開されていません。2023/8/15に公開されたChilliCream社の[Blog](https://chillicream.com/blog/2023/08/15/graphql-fusion)、2023/11に公開されたAWS AppSyncの[Blog](https://aws.amazon.com/jp/blogs/mobile/graphql-gateway-based-federation-with-aws-appsync-and-graphql-fusion/)の情報くらいしかありません。
GraphQLConf 2023ではChilliCreamの[Michael Staib](https://github.com/michaelstaib)さんの講演で紹介されていました。

Fusionは以下の4つのメジャーコンポーネントを持っています。
- Schema Composition(スキーマ構成)
    - ディレクティブ
    - スキーマのマージ方法
    - スキーマの実行方法
    - クエリプランニング
- Gateway Configuration
- Remote Executor
- Telemetry

メインどころのSchema Compositionについて説明します。

例としてUserという似たタイプを持ったAccountサービスとReviewsサービスを用います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636552/48d1d07e-8952-1ad1-7322-7200d0d81f25.png" width=100%>

Fusionでは以下のようにマージされます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636552/b75dbe5b-b649-6db7-95ae-57c7944478cd.png" width=100%>

ポイントはnull許容と重複です。
1つ目のポイントnull許容について、マージ後のスキーマで`id`はnullを許容しています。これはAccountサービスが`id: ID`と定義されておりnullを許容しているためです。つまり1つでもnullを許容するサービス(Subgraph)があればマージ後のスキーマもnullを許容する仕様です。

2つ目のポイントは重複した項目の扱いです。`id`と`name`が重複した項目であり、マージ後1つの項目に集約されています。Fusionは同じ名前を持つフィールドと型を衝突として扱うのではなく、それらを重複として認識します。

マージ後のスキーマ定義は実際には以下のようにディレクティブが付与されたものになります。

```graphql:マージ後のスキーマ定義
type User
  @variable(subgraph: "Reviews", name: "User_id", select: "id")
  @variable(subgraph: "Account", name: "User_id", select: "id")
  @variable(subgraph: "Account", name: "User_name", select: "name")
  @resolver(
    subgraph: "Reviews"
    select: "{ userById(id: $id) }"
    arguments: [{ name: "User_id", type: "ID!" }]
  )
  @resolver(
    subgraph: "Account"
    select: "{ userById(id: $id) }"
    arguments: [{ name: "User_id", type: "ID!" }]
  )
  @resolver(
    subgraph: "Account"
    select: "{ userByName(name: $name) }"
    arguments: [{ name: "User_name", type: "String!" }]
  ){
  id: ID! @source(subgraph: "Reviews") @source(subgraph: "Account")
  name: String! @source(subgraph: "Reviews") @source(subgraph: "Account")
  email: String! @source(subgraph: "Account")
}
```
`@resolver`というディレクティブが付いています。`select`で指定されているクエリでバックエンドサービスにリクエストを送りデータを取得します。
Accountサービスに対する`@resolver`が2つ定義されています。この時にクエリプランニングを通して最適なリゾルバが実行されるようになります。

このようにディレクティブ/スキーマのマージ方法/クエリプランニング等の仕様がFusionによって定義されていくのだと思います。なんとなく雰囲気を理解できたでしょうか。

ちなみに2023/12/11時点でFusionを実装したサーバーはChilliCream社が開発している[Hot Chocolate](https://chillicream.com/docs/hotchocolate/v13)のみです。まだ仕様が公開されていないですし当然ですね。

## 比較

さてそれぞれの仕様の概要を掴めた?ところでそれぞれの比較をしたくなります。
[WunderGraphの記事](https://wundergraph.com/blog/open_federation_announcement)で以下のように書かれています。

> 多くのユースケースでは、フェデレーションされたGraphQL APIで十分であり、Open Federationを採用または使用しない理由はありません。
ただし、フェデレーション GraphQL API だけでなく、REST API、GRPC API、AsyncAPI なども構成したいユースケースがあります。 そこで、GraphQL Fusionの出番です。

なので以下のようにバックエンドサービスに応じてGatewayサーバを選定すると良さそう??
- GraphQL APIのみの場合
  → Open Federationを実装したGateway
- GraphQL、REST、gRPC、非同期のような様々なAPI規格の場合
  → Fusionを実装したGateway

と思いましたが、FusionがOpen Federationを包含しているように思えます。それならFusionだけで良いのでは??と思っていたら最後にこんなことが書かれていました。

> Federated GraphQLは成熟したテクノロジーであり、長年にわたって本番環境で使用されてきました。 GraphQL Fusionはまだ初期段階にあり、同じレベルの成熟度に達するには時間がかかるでしょう。
私たちは両方の技術に賭けており、互いに非常にうまく補完し合うと信じています。 この2つのテクノロジーが共存するのか、それともいずれ一方が他方を支配するようになるのかは、時間が経てばわかるでしょう。 私たちにとって最も重要なのは、APIの構成を標準化して、より良いGraphQLエコシステムを構築することです。

ということでどちらの仕様に準じるべきか**結局のところもう少し様子見する必要がありそう**です。仕様策定に参画している団体も名の知れた企業が多いですしなんとなくFusionを信じておけば良いのかなぁという気がします。


# Hot ChocolateのFusion機能の紹介

Hot ChocolateはC#のGraphQLサーバーです。
Fusionは機能としては13系のリリースに含まれています。ですが2023/12/11時点での公式ドキュメントではFusionに関する記載はありません。

https://chillicream.com/blog/2023/02/08/new-in-hot-chocolate-13

ただexampleの中にGraphQLConf 2023で使っていたサンプルアプリがありました。気になる方は動かしてみてください。
https://github.com/ChilliCream/hotchocolate-examples/tree/master/misc/Fusion1


# まとめ
今回はインターネット上の情報をかき集めて、Fusionを中心に分散GraphQLを実現するGateway周りの動向をご紹介しました。
まだまだ仕様策定が始まったばかりなので今すぐに使えるものではありません。
ただHasura、AWS AppSyncなども仕様策定に関わっておりFusionを実装していくと考えられます。The GuildはGraphQL Meshとは別のConductor GatewayというGraphQL GatewayのOSSを開発しているようです。

https://the-guild.dev/graphql/gateway

今後もGraphQL Gatewayの動向を注視していきたいと思います。