---
title: "Apache APISIX と gRPC-Web の統合 - API7.ai"
description: "gRPC Web 简介 gRPC 最初由 Google 开发，是一种高性能的远程..."
url: "https://api7.ai/ja/blog/integration-with-grpc-web"
---

[Blog](https://api7.ai/ja/blog)

[Products](https://api7.ai/ja/category/products)[Technology](https://api7.ai/ja/category/technology)[Ecosystem](https://api7.ai/ja/category/ecosystem)[Case Study](https://api7.ai/ja/category/usercase)[Team & Community](https://api7.ai/ja/category/community)

Search

⌘ + K

[Blog](https://api7.ai/blog)

Ecosystem

# Apache APISIX と gRPC-Web の統合

Fei Han

January 25, 2022

[Ecosystem](https://api7.ai/category/ecosystem)

## gRPC Web 紹介

Googleによって最初に開発されたgRPCは、HTTP/2上に実装された高性能なリモートプロシージャコールフレームワークです。しかし、ブラウザが直接HTTP/2を公開していないため、WebアプリケーションはgRPCを直接使用できません。gRPC Webはこの問題を解決する標準化されたプロトコルです。

最初のgRPC-web実装は2018年にJavaScriptライブラリとしてリリースされ、WebアプリケーションがgRPCサービスと直接通信できるようになりました。その原理は、HTTP/1.1およびHTTP/2と互換性のあるエンドツーエンドのgRPCパイプラインを作成することです。ブラウザは通常のHTTPリクエストを送信し、ブラウザとサーバーの間に位置するgRPC-Webプロキシがリクエストとレスポンスを変換します。gRPCと同様に、gRPC WebはWebクライアントとバックエンドのgRPCサービスの間で事前に定義された契約を使用します。メッセージのシリアライズとエンコードにはProtocol Buffersが使用されます。

![gRPC-webの動作原理](https://static.api7.ai/2022/10/03/633a423516b37.png?imageMogr2/format/webp)

gRPC Webを使用すると、ユーザーはブラウザまたはNodeクライアントを使用してバックエンドのgRPCアプリケーションを直接呼び出すことができます。ただし、ブラウザ側でgRPCサービスを呼び出すためにgRPC-Webを使用するにはいくつかの制限があります。

- クライアント側ストリーミングおよび双方向ストリーミング呼び出しはサポートされていません。
- クロスドメインでgRPCサービスを呼び出すには、サーバー側でCORSを設定する必要があります。
- gRPCサーバー側はgRPC-Webをサポートするように設定するか、ブラウザとサーバーの間の呼び出しを変換するためのサードパーティサービスエージェントが利用可能である必要があります。

## Apache APISIX gRPC Web プロキシ

Apache APISIXは、プラグインを通じてgRPC Webプロトコルのプロキシをサポートしています。`grpc-web`プラグインでは、gRPC WebがgRPC Serverと通信する際のプロトコル変換とデータコーデックの作業が行われ、その通信プロセスは以下の通りです。

gRPC Webクライアント -> Apache APISIX（プロトコル変換 & データコーデック） -> gRPCサーバー

以下は、gRPC Webクライアントを構築し、Apache APISIXを通じてgRPC Webリクエストをプロキシする方法を示す完全な例です。以下の例では、GoをgRPCサーバーのハンドラとして、NodeをgRPC Webクライアントのリクエスタとして使用します。

## Protocol Bufferの設定

最初に、Protocol Bufferコンパイラと関連プラグインをインストールします。

1. `protoc`と`proto-grpc-*`をインストールします。

   Protocol Bufferコンパイラ`protoc`と、`.proto`ファイルからGo、JavaScript、およびgRPC Webインターフェースコードを生成するための`protoc-gen-go`および`protoc-gen-grpc-web`プラグインをシステムにインストールする必要があります。

   以下のスクリプトを実行して上記のコンポーネントをインストールしてください。

   ```
   #!/usr/bin/env bash

   set -ex

   PROTOBUF_VERSION="3.19.0"
   wget https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
   unzip protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
   mv bin/protoc /usr/local/bin/protoc
   mv include/google /usr/local/include/
   chmod +x /usr/local/bin/protoc

   PROTO_GO_PLUGIN_VER="1.2.0"
   wget https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v${PROTO_GO_PLUGIN_VER}/protoc-gen-go-grpc.v${PROTO_GO_PLUGIN_VER}.linux.amd64.tar.gz
   tar -zxvf protoc-gen-go-grpc.v${PROTO_GO_PLUGIN_VER}.linux.amd64.tar.gz
   mv protoc-gen-go-grpc /usr/local/bin/protoc-gen-go
   chmod +x /usr/local/bin/protoc-gen-go

   PROTO_JS_PLUGIN_VER="1.3.0"
   wget https://github.com/grpc/grpc-web/releases/download/${PROTO_JS_PLUGIN_VER}/protoc-gen-grpc-web-${PROTO_JS_PLUGIN_VER}-linux-x86_64
   mv protoc-gen-grpc-web-${PROTO_JS_PLUGIN_VER}-linux-x86_64 /usr/local/bin/protoc-gen-grpc-web
   chmod +x /usr/local/bin/protoc-gen-grpc-web
   ```

2. `SayHello`の例となる`proto`ファイルを作成します。

   ```
   // a6/echo.proto

   syntax = "proto3";

   package a6;

   option go_package = "./;a6";

   message EchoRequest {
   string message = 1;
   }

   message EchoResponse {
   string message = 1;
   }

   service EchoService {
   rpc Echo(EchoRequest) returns (EchoResponse);
   }
   ```

## サーバー側アプリケーションの設定

1. サーバー側のGo生メッセージとサービス/クライアントスタブを生成します。

   ```
   protoc -I./a6 echo.proto --go_out=plugins=grpc:./a6
   ```

2. サーバー側のハンドラインターフェースを実装します。

   ```
   // a6/echo.impl.go

   package a6

   import (
   "errors"
   "golang.org/x/net/context"
   )

   type EchoServiceImpl struct {
   }

   func (esi *EchoServiceImpl) Echo(ctx context.Context, in *EchoRequest) (*EchoResponse, error) {
   if len(in.Message) <= 0 {
       return nil, errors.New("message invalid")
   }
   return &EchoResponse{Message: "response: " + in.Message}, nil
   }
   ```

3. サーバー側アプリケーションの実行エントリファイル。

   ```
   // server.go
   package main

   import (
   "fmt"
   "log"
   "net"

   "apisix.apache.org/example/a6"
   "google.golang.org/grpc"
   )

   func main() {
   lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 50001))
   if err != nil {
       log.Fatalf("failed to listen: %v", err)
   }

   grpcServer := grpc.NewServer()
   a6.RegisterEchoServiceServer(grpcServer, &a6.EchoServiceImpl{})

   if err = grpcServer.Serve(lis); err != nil {
       log.Fatalf("failed to serve: %s", err)
   }
   }
   ```

4. サーバー側サービスをコンパイルして起動します。

   ```
   go build -o grpc-server server.go
   ./grpc-server
   ```

## クライアントプログラムの設定

1. クライアント側の`proto`コードを生成します。

   gRPC WebのJavaScript用に、クライアント側のJavaScript生メッセージ、サービス/クライアントスタブ、およびインターフェースコードを生成します。

   gRPC Webの`proto`プラグインは、2つのモードのコード生成を提供します。

   1. mode=grpcwebtext: デフォルトの生成コードは、ペイロードをgrpc-web-text形式で送信します。

   - Content-type: application/grpc-web-text
   - ペイロードはbase64エンコードを使用
   - 単項およびサーバーストリーミング呼び出しをサポート

   1. mode=grpcweb: ペイロードをバイナリprotobuf形式で送信します。

   - Content-type: application/grpc-web+proto
   - ペイロードはバイナリprotobuf形式
   - 現在は単項呼び出しのみサポート

   ```
   protoc -I=./a6 echo.proto --js_out=import_style=commonjs:./a6 --grpc-web_out=import_style=commonjs,mode=grpcweb:./a6
   ```

2. クライアント側の依存関係をインストールします。

   ```
   npm i grpc-web
   npm i google-protobuf
   ```

3. クライアント側のエントリファイルを実行します。

   ```
   // client.js
   const {EchoRequest} = require('./a6/echo_pb');
   const {EchoServiceClient} = require('./a6/echo_grpc_web_pb');
   // Apache APISIXのエントリに接続
   let echoService = new EchoServiceClient('http://127.0.0.1:9080');

   let request = new EchoRequest();
   request.setMessage("hello")

   echoService.echo(request, {}, function (err, response) {
      if (err) {
           console.log(err.code);
           console.log(err.message);
       } else {
           console.log(response.getMessage());
       }
   });
   ```

4. 最終的なプロジェクト構造

   ```
   $ tree .
   ├── a6
   │   ├── echo.impl.go
   │   ├── echo.pb.go
   │   ├── echo.proto
   │   ├── echo_grpc_web_pb.js
   │   └── echo_pb.js
   ├── client.js
   ├── server.go
   ├── go.mod
   ├── go.sum
   ├── package.json
   └── package-lock.json
   ```

上記の手順を完了すると、gRPCサーバーサーバーアプリケーションとgRPC Webクライアントアプリケーションを設定し、サーバーアプリケーションを起動しました。サーバーアプリケーションはポート`50001`でリクエストを受信します。

## Apache APISIXの設定

次に、Apache APISIXのルーティングプラグイン設定で`grpc-web`プラグインを有効にして、gRPC Webリクエストをプロキシします。

1. `grpc-web`プロキシプラグインを有効にします。

   ルーティングは**プレフィックスマッチング**を使用する必要があります（例：`/*`または`/grpc/example/*`）。gRPC WebクライアントはURIに`proto`で宣言されたパッケージ名、サービスインターフェース名、メソッド名などを渡すため（例：`/path/a6.EchoService/Echo`）、**絶対マッチを使用するとプラグインがURIから`proto`情報を抽出できなくなります**。

   ```
   $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
   {
       "uri":"/*", // プレフィックスマッチングモード
       "plugins":{
           "grpc-web":{} // gRPC Webプラグインを有効化
       },
       "upstream":{
           "scheme":"grpc",
           "type":"roundrobin",
           "nodes":{
               "127.0.0.1:50001":1 // gRPCサーバーのリスンアドレスとポート
           }
       }
   }'
   ```

2. gRPC Webプロキシリクエストを検証します。

   Nodeから`client.js`を実行して、gRPC WebプロトコルリクエストをApache APISIXに送信できます。

   上記のクライアント側とサーバー側の処理ロジックはそれぞれ、クライアントがサーバーに`hello`というメッセージを送信し、サーバーがメッセージを受信して`response: hello`と応答するものです。実行結果は以下の通りです。

   ```
   $ node client.js
   response: hello
   ```

3. `grpc-web`プロキシプラグインを無効にします。

   ルーティングプラグイン設定からgrpc-web属性を削除するだけです。

   ```
   $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
   {
       "uri":"/*",
       "plugins":{
       },
       "upstream":{
           "scheme":"grpc",
           "type":"roundrobin",
           "nodes":{
               "127.0.0.1:50001":1
           }
       }
   }'
   ```

## まとめ

この記事では、Apache APISIXで`grpc-web`を使用するための実践的な経験を紹介しました。

[GitHub Discussions](https://github.com/apache/apisix/discussions)でディスカッションを開始したり、[メーリングリスト](https://apisix.apache.org/zh/docs/general/subscribe-guide)を通じてコミュニケーションを取ることを自由に行ってください。

Tags:

[APISIX Basics](https://api7.ai/tags/apisix-basics)

[gRPC-Web](https://api7.ai/tags/grpc-web)

Share article link

Share

Related Posts

[![マイクロサービスはなぜAPIゲートウェイを必要とするのか](https://static.api7.ai/uploads/2023/02/16/CHqaC3Xw_Ecosystem%20%E6%A8%A1%E6%9D%BF1.png)](https://api7.ai/blog/why-do-microservices-need-an-api-gateway)

## [マイクロサービスはなぜAPIゲートウェイを必要とするのか](https://api7.ai/blog/why-do-microservices-need-an-api-gateway)

[![Amazon Lambdaを使用する際にApache APISIXが必要な理由](https://static.api7.ai/uploads/2024/12/25/PGShc0sm_apisix-aws-lambda.png)](https://api7.ai/blog/why-do-you-need-apache-apisix-when-using-amazon-lambda)

## [Amazon Lambdaを使用する際にApache APISIXが必要な理由](https://api7.ai/blog/why-do-you-need-apache-apisix-when-using-amazon-lambda)

Table of Contents

- [gRPC Web 紹介](#grpc-web-%E7%B4%B9%E4%BB%8B)
- [Apache APISIX gRPC Web プロキシ](#apache-apisix-grpc-web-%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7)
- [Protocol Bufferの設定](#protocol-buffer%E3%81%AE%E8%A8%AD%E5%AE%9A)
- [サーバー側アプリケーションの設定](#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E5%81%B4%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%A8%AD%E5%AE%9A)
- [クライアントプログラムの設定](#%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E8%A8%AD%E5%AE%9A)
- [Apache APISIXの設定](#apache-apisix%E3%81%AE%E8%A8%AD%E5%AE%9A)
- [まとめ](#%E3%81%BE%E3%81%A8%E3%82%81)

## Related Posts

[![カスタマイズされたソリューションの解放：Apache APISIXとNode-Redの調和を活用する](https://static.api7.ai/uploads/2024/03/06/uppjizMq_APISIX-node-red-cover.png)](https://api7.ai/ja/blog/apache-apisix-and-node-red)

Ecosystem

March 6, 2024

#### [カスタマイズされたソリューションの解放：Apache APISIXとNode-Redの調和を活用する](https://api7.ai/ja/blog/apache-apisix-and-node-red)

APISIXとNode-Redを組み合わせることで、複雑なコードやプラグインを書き直すことなく、視覚的に完全なリクエスト処理プロセスを実装することができます。

[Node-Red](https://api7.ai/tags/node-red)

[APISIX Basics](https://api7.ai/tags/apisix-basics)

[![APIを保護するための深掘り：WAFとAPI Gatewayの統合](https://static.api7.ai/uploads/2024/01/29/xV7L0ef7_APISIX_WAF_Cover.jpeg)](https://api7.ai/ja/blog/waf-and-api-gateway-integration)

Ecosystem

January 30, 2024

#### [APIを保護するための深掘り：WAFとAPI Gatewayの統合](https://api7.ai/ja/blog/waf-and-api-gateway-integration)

ベストプラクティスに従い、適切なツールを導入することで、幅広い攻撃からAPIを保護する堅牢なセキュリティレイヤーを構築できます。

[WAF](https://api7.ai/tags/waf)

[APISIX Basics](https://api7.ai/tags/apisix-basics)

[![mTLS Everywhere: APISIX の TLS 設定方法](https://static.api7.ai/uploads/2024/12/24/DVhnbLpy_apisix-mtls.png)](https://api7.ai/ja/blog/configure-tls-for-apisix)

Ecosystem

July 31, 2023

#### [mTLS Everywhere: APISIX の TLS 設定方法](https://api7.ai/ja/blog/configure-tls-for-apisix)

Transport Secure Layer（TLS），以前称为SSL，是信息系统安全的众多支柱之一。让我们来学习如何为Apache APISIX API Gateway配置TLS。

[APISIX Basics](https://api7.ai/tags/apisix-basics)

[API Security](https://api7.ai/tags/api-security)
