Mengintegrasikan Apache APISIX dengan gRPC-Web

Fei Han

January 25, 2022

Ecosystem

Pengenalan gRPC Web

Awalnya dikembangkan oleh Google, gRPC adalah kerangka kerja pemanggilan prosedur jarak jauh berkinerja tinggi yang diimplementasikan pada HTTP/2. Namun, karena browser tidak secara langsung mengekspos HTTP/2, aplikasi Web tidak dapat menggunakan gRPC secara langsung. gRPC Web adalah protokol standar yang memecahkan masalah ini.

Implementasi pertama gRPC-web dirilis pada tahun 2018 sebagai pustaka JavaScript yang memungkinkan aplikasi Web berkomunikasi langsung dengan layanan gRPC. Prinsipnya adalah membuat pipa gRPC ujung ke ujung yang kompatibel dengan HTTP/1.1 dan HTTP/2. Browser kemudian mengirim permintaan HTTP biasa, dan proxy gRPC-Web yang terletak di antara browser dan server menerjemahkan permintaan dan respons. Mirip dengan gRPC, gRPC Web menggunakan kontrak yang telah ditentukan antara klien Web dan layanan gRPC back-end. Protocol Buffers digunakan untuk menyerialisasi dan mengkodekan pesan.

bagaimana gRPC-web bekerja

Dengan gRPC Web, pengguna dapat memanggil aplikasi gRPC back-end langsung menggunakan browser atau klien Node. Namun, ada beberapa batasan dalam menggunakan gRPC-Web di sisi browser untuk memanggil layanan gRPC.

  • Streaming sisi klien dan panggilan streaming dua arah tidak didukung.
  • Memanggil layanan gRPC lintas domain memerlukan konfigurasi CORS di sisi server.
  • Sisi server gRPC harus dikonfigurasi untuk mendukung gRPC-Web, atau layanan agen pihak ketiga harus tersedia untuk menerjemahkan panggilan antara browser dan server.

Apache APISIX gRPC Web Proxy

Apache APISIX mendukung proxy protokol gRPC Web melalui plugin, yang menyelesaikan pekerjaan konversi protokol dan pengkodean data saat gRPC Web berkomunikasi dengan gRPC Server dalam plugin grpc-web, dan proses komunikasinya adalah sebagai berikut.

gRPC Web Client -> Apache APISIX (konversi protokol & pengkodean data) -> gRPC server

Berikut adalah contoh lengkap yang menunjukkan cara membangun gRPC Web Client dan memproksi permintaan gRPC Web melalui Apache APISIX. Dalam contoh berikut, kita akan menggunakan Go sebagai penangan server gRPC Server dan Node sebagai peminta klien gRPC Web.

Konfigurasi Protocol Buffer

Langkah pertama adalah menginstal kompiler Protocol Buffer dan plugin terkait.

  1. Instal protoc dan proto-grpc-*.

    Kompiler Protocol Buffer protoc dan plugin protoc-gen-go serta protoc-gen-grpc-web untuk menghasilkan kode antarmuka Go, JavaScript, dan gRPC web untuk .proto perlu diinstal di sistem Anda sebelum menulis aplikasi klien dan server.

    Jalankan skrip berikut untuk menginstal komponen di atas.

    #!/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. Buat contoh file proto SayHello.

    // 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); }

Konfigurasi Aplikasi Server

  1. Hasilkan pesan mentah Go sisi server dan stub layanan/klien.

    protoc -I./a6 echo.proto --go_out=plugins=grpc:./a6
  2. Implementasikan antarmuka penangan server.

    // 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. File entri runtime aplikasi server.

    // 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. Kompilasi dan mulai layanan server.

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

Konfigurasi Program Klien

  1. Hasilkan kode proto sisi klien.

    Hasilkan pesan mentah JavaScript sisi klien, stub layanan/klien, dan kode antarmuka untuk JavaScript gRPC Web.

    Plugin proto untuk gRPC Web menyediakan dua mode pembuatan kode.

    1. mode=grpcwebtext: Kode yang dihasilkan secara default mengirim payload dalam format grpc-web-text.

    • Content-type: application/grpc-web-text

    • Payload menggunakan pengkodean base64

    • Mendukung panggilan unary dan streaming server

    1. mode=grpcweb: mengirim payload dalam format protobuf biner.

    • Content-type: application/grpc-web+proto
    • Payload dalam format protobuf biner
    • Saat ini hanya mendukung panggilan unary
    protoc -I=./a6 echo.proto --js_out=import_style=commonjs:./a6 --grpc-web_out=import_style=commonjs,mode=grpcweb:./a6
  2. Instal dependensi sisi klien.

    npm i grpc-web npm i google-protobuf
  3. Jalankan file entri di sisi klien.

    // client.js const {EchoRequest} = require('./a6/echo_pb'); const {EchoServiceClient} = require('./a6/echo_grpc_web_pb'); // terhubung ke pintu masuk 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. Struktur proyek akhir

    $ 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

Setelah menyelesaikan langkah-langkah di atas, Anda telah mengkonfigurasi aplikasi server gRPC Server dan aplikasi klien gRPC Web, dan memulai aplikasi server, yang akan menerima permintaan pada port 50001.

Konfigurasi Apache APISIX

Selanjutnya, cukup aktifkan plugin grpc-web dalam konfigurasi plugin routing Apache APISIX untuk memproksi permintaan gRPC web.

  1. Aktifkan plugin proxy grpc-web.

    Routing harus menggunakan pencocokan awalan (misalnya, /* atau /grpc/example/*), karena klien gRPC web meneruskan nama paket, nama antarmuka layanan, nama metode, dll. yang dideklarasikan dalam proto di URI (misalnya, /path/a6.EchoService/Echo), menggunakan pencocokan absolut akan mencegah plugin mengekstrak informasi proto dari URI.

    $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri":"/*", // mode pencocokan awalan "plugins":{ "grpc-web":{} // aktifkan plugin gRPC Web }, "upstream":{ "scheme":"grpc", "type":"roundrobin", "nodes":{ "127.0.0.1:50001":1 // Alamat dan port Listen gRPC Server } } }'
  2. Validasi Permintaan Proxy gRPC Web.

    Permintaan protokol gRPC Web dapat dikirim ke Apache APISIX dengan menjalankan client.js dari Node.

    Logika pemrosesan sisi klien dan server di atas masing-masing adalah: klien mengirim pesan ke server dengan konten hello, server menerima pesan dan merespons dengan response: hello, dan hasil eksekusinya adalah sebagai berikut.

    $ node client.js response: hello
  3. Nonaktifkan plugin proxy grpc-web.

    Cukup hapus atribut grpc-web dari konfigurasi plugin routing.

    $ 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 } } }'

Ringkasan

Artikel ini memberikan pengalaman langsung tentang penggunaan grpc-web di Apache APISIX.

Jangan ragu untuk memulai diskusi di GitHub Discussions atau berkomunikasi melalui mailing list.

Tags: