細粒度のGraphQLアクセス制御とクエリパフォーマンスの最適化

GraphQLは、APIのためのクエリ言語であり、既存のデータでそのクエリを実行するためのランタイムです。API内で利用可能なデータの包括的かつ明確な説明を提供し、クライアントが余分なデータなしに必要なものだけを正確に要求できるようにし、APIの進化を促進し、堅牢な開発者ツールをサポートします。

GraphQLアクセス制御とクエリ最適化

アクセス制御

認可は、ユーザー、セッション、またはコンテキストが特定のアクションを実行したり、特定のデータを表示したりするためのアクセス制御リスト(ACL)を持っているかどうかを決定するルールまたはビジネスロジックのセットです。

そのような動作はビジネスロジック層で強制されるべきです。認可ロジックを直接GraphQL層に置くことは魅力的かもしれませんが、一般的には他の場所で処理する方が適切です。

クエリ最適化

GraphQLクエリの最適化には、応答時間を改善し、サーバーの負荷を軽減するために、不要なデータの取得と処理を最小限に抑える技術が含まれます。これにより、より効率的なアプリケーションが実現し、ユーザー体験が向上し、ユーザーエンゲージメントと保持が強化され、サーバーのスケーラビリティが向上します。

GraphQLクエリを最適化する方法

  • N+1(バッチロード)
  • 過剰取得と過少取得
  • レイテンシを減らすためのキャッシング
  • ページネーション

GraphQLアクセス制御の強化とGraphQLクエリ最適化

認証エンジンは、ACL(アクセス制御リスト)を使用してノードおよびフィールドの権限を検証し、権限に基づいてGraphQLクエリを最適化します。さらに、N+1リゾルバはクエリを統合することでパフォーマンスを向上させます。このアプローチはN+1問題に対処します。

Figure 1



アクター

  • GraphQLクエリ: 特定のデータを取得するためにクライアントからGraphQLサーバーに送信されるリクエスト。
  • GraphQLエンジン: GraphQLクエリを実行することを可能にするサービスを指します。
  • 認証エンジン: ACLを使用してノードおよびフィールドの権限を検証し、フィールド権限に基づいてGraphQLクエリを最適化します。
  • N+1リゾルバ: 複数のデータベースクエリに関連するオーバーヘッドとレイテンシを削減し、パフォーマンスと効率を向上させます。

Figure 2

Figure 3

アクセス制御の強化

既存の実装

アプリに製品、ベンダー、住所があると仮定しましょう。ベンダーと住所のデータにアクセスするにはユーザー認証が必要であり、これはリゾルバで簡単に処理できます。

ただし、ベンダーデータは管理者ユーザーに制限されており、一部のベンダーフィールドは特定の役割にのみアクセス可能です。一方、製品は公開されており、製品所有者の役割で表示できます。言及されたクエリ(図3)を実行すると、セキュリティの問題を引き起こす可能性があるため、製品データと関連するベンダーデータおよび住所データが返されます。

拡張実装

クエリのノードとフィールドはユーザーの許可に従って検証され、最適化されたGraphQLクエリが生成されます。

Figure 3.1 (Flow Diagram)

 

Figure 4

図4は、Node.jsを使用してGraphQL APIでカスタム認証を実装する方法の例です。このコードでは、役割がAuthorizationヘッダーから抽出され、その後クエリと共に使用されて認証が検証されます。

Figure 5

この例では、セッションまたはリクエストからユーザーの役割と権限を使用して、GraphQLスキーマ内の特定のクエリとミューテーションへのアクセスを制御しています。

このメソッドは、すべてのノードとフィールドで役割と権限を再帰的にチェックします。ノードやフィールドが許可されていない場合、構成に基づいて次のアクションのいずれかを実行します:

  • ノードまたはフィールドを削除します。
  • エラーメッセージ付きのフィールドまたはノードを返します。
  • 例外をスローします。

GraphQLクエリがスキーマに対して検証されると、このメソッドは最適化されたGraphQLクエリを返します。

N+1を使用したORMクエリの最適化の強化

既存の実装

クエリのパフォーマンスに影響を与える技術的な問題です。これは、データベースにアクセスするためにオブジェクト関係マッピング(ORM)フレームワークを使用するアプリケーションで発生する可能性があります。

通常、アプリケーションがデータベースから関連するエンティティのコレクションをロードする必要がある場合に発生します。

2つの製品があると仮定してください。製品を取得するために1つのクエリを実行し、各製品のベンダーを個別に取得するために2つの追加クエリが必要です。

Figure 6

Figure 7

1つのクエリは製品のリストを取得し、別個のクエリは各製品のベンダーを取得します。ベンダーのクエリ数は製品数と同じです。

強化された実装

リクエストがN+1リゾルバに達すると、N+1リゾルバは、メインデータのための単一のクエリと関連データのための追加クエリに削減してデータベースリクエストの数を最小限に抑えるようにクエリを最適化し、効果的にN+1問題を軽減します。

  1. メインデータクエリ: アプリケーションで必要な主要なデータセットを取得する単一クエリ。
  2. 関連データクエリ: データセットを完成させるために必要な関連データを取得する追加クエリ。

Figure 8

Figure 9: Total No. of Queries are 2 (1 for Product, 1 for Vendor)

Figure 10

すべてのクエリリゾルバが完了した後、サーバーは最適化されたデータをJSON形式でクライアントに返します。

結論

弊社は、GraphQL API のセキュリティを確保するために、細かい認可メカニズムと強化されたセキュリティ対策の実装が重要であることを明確にしました。これには、ノードレベルとフィールドレベルのセキュリティが含まれます。

この記事に記載されているように、N+1問題は最適化されていないクエリがGraphQLで過剰なデータベース呼び出しを引き起こすと発生します。N+1問題を克服するための解決策を提供しています。これによりデータベースサーバーのリソース使用量が減少し、コスト削減とスケーラビリティの向上が実珅します。さらに、クエリのパフォーマンスを向上させることで、クエリの応答時間を短縮することにより、ユーザーエクスペリエンスが向上します。

Source:
https://dzone.com/articles/optimizing-fine-grained-graphql-access-control-and-queries