はじめに

ストリーミングは、APIが大量のデータとリアルタイムの更新を効率的に 処理できるようにする強力な機能です。Goaのストリーミングサポートにより、 一連の結果を送受信できるエンドポイントを定義でき、サービスの応答性と スケーラビリティを向上させることができます。

ストリーミングが重要な理由

  • 効率性: 単一の接続で継続的なデータ転送を可能にすることで、 複数のHTTPリクエストのオーバーヘッドを削減します。
  • リアルタイムデータ: ライブフィード、通知、データモニタリングなどの アプリケーションに不可欠なリアルタイムデータ更新を可能にします。
  • スケーラビリティ: データセット全体をメモリにロードするのではなく、 チャンク単位でデータを処理することで、大規模なデータセットをより 適切に処理します。
  • ユーザー体験の向上: データを段階的に配信することで、ユーザーに よりスムーズで応答性の高い体験を提供します。

Goaのストリーミング機能

大きなファイルやリアルタイムデータストリームを扱う場合、処理前に ペイロード全体をメモリにロードすることは、必ずしも実現可能でも 望ましくもありません。Goaはストリーミングデータを処理するための 複数のアプローチを提供します:

StreamingPayloadStreamingResultの使用ケース:

  • 既知の型を持つ構造化データのストリーミング
  • Goaの型システムとバリデーションの活用
  • gRPCストリーミングの利用

SkipRequestBodyEncodeDecodeSkipResponseBodyEncodeDecodeの使用ケース:

  • 生のバイナリデータや未知のコンテンツタイプのストリーミング
  • カスタムストリーミングプロトコルの実装
  • マルチメディアストリームの処理

GoaはHTTP(WebSocketsを使用)やgRPCなど、異なるトランスポートプロトコル上で 単方向および双方向のストリーミングをサポートします。Goaのドメイン固有言語(DSL)を 活用することで、トランスポートに依存しないストリーミングエンドポイントを 定義でき、サービスアーキテクチャにおけるシームレスな統合と柔軟性を 実現できます。

主な機能

  • 単方向ストリーミング: サーバーまたはクライアントがデータストリームを送信できます。
  • 双方向ストリーミング: サーバーとクライアントが同時にデータストリームを送信できます。
  • トランスポート独立性: 複数のトランスポートプロトコルで修正なしで動作するストリーミングロジックを定義します。
  • 生成されたストリームインターフェース: ストリーミング定義に基づいて、サーバーとクライアントのストリームインターフェースを自動生成します。
  • カスタムビュー: ストリーミング結果に対して複数のビューをサポートし、クライアントへのデータ表示方法の柔軟性を提供します。

例の概要

ログエントリを管理するloggerサービスを見てみましょう。実際のユースケースを 示すさまざまなストリーミングシナリオを紹介します。HTTPを介して生のバイナリ データをストリーミングする方法については、HTTPを介した生のバイナリデータの ストリーミングセクションを参照してください。

サーバーサイドストリーミングの例

var _ = Service("logger", func() {
    // サーバーが特定のトピックのログエントリをストリーミング
    Method("subscribe", func() {
        Description("特定のトピックのログエントリをストリーミング")
        
        Payload(func() {
            Field(1, "topic", String, "購読するログのトピック")
            Required("topic")
        })
        
        // サーバーがログエントリをストリーミング
        StreamingResult(func() {
            Field(1, "timestamp", String, "読み取り時刻")
            Field(2, "message", String, "ログメッセージ")
            Required("timestamp", "message")
        })

        HTTP(func() {
            GET("/logs/{topic}/stream")
            Response(StatusOK)
        })
    })
})

双方向ストリーミングの例

var _ = Service("logger", func() {
    // 双方向ストリーミングによるリアルタイムログ管理
    Method("subscribe", func() {
        Description("リアルタイムログ更新とトピック管理のための双方向ストリーミング")
        
        // クライアントがトピック更新をストリーミング
        StreamingPayload(func() {
            Field(1, "topic", String, "購読するログのトピック")
            Required("topic")
        })
        
        // サーバーがログメッセージをストリーミング
        StreamingResult(func() {
            Field(1, "timestamp", String, "読み取り時刻")
            Field(2, "message", String, "ログメッセージ")
            Required("timestamp", "message")
        })

        HTTP(func() {
            GET("/logs/{topic}/stream")
            Response(StatusOK)
        })
    })
})

これらの例は以下を示しています:

1. サーバーサイドストリーミング

サーバーが単一のクライアントリクエストに対して複数のレスポンスを送信する 一方向のストリーミングパターン。

例:ログモニタリング

クライアントリクエスト(1回): "データベースエラーのログを監視"

サーバーレスポンス(継続的):
10:00:01 - データベース接続タイムアウト
10:00:05 - クエリ実行失敗
10:00:08 - 接続プール枯渇
(新しいログが発生するたびに送信を継続)

主な特徴: 初期リクエスト後、データはサーバーからクライアントへの 一方向のみで流れます。

2. 双方向ストリーミング

両側が時間とともに複数のメッセージを送信できるパターン。

例:インタラクティブなログ管理

クライアント: "データベースのログのモニタリングを開始"
サーバー: *データベース関連のログを送信*
クライアント: "ネットワークも含むようにフィルターを更新"
サーバー: *データベースとネットワークの両方のログを送信*
クライアント: "データベースフィルターを削除"
サーバー: *ネットワークログのみを送信*
(両側が通信を継続)

主な特徴: 接続の存続期間中、クライアントとサーバーの両方が複数の メッセージを送信できる継続的な双方向通信を可能にします。

次のステップ

Goaのストリーミングに関するこの導入を通じて、ストリーミングエンドポイントの 設計、実装、管理についてより深く学ぶ準備が整いました。以降のセクションでは 以下の内容を説明します: