---
title: "Интеграция Apache APISIX с gRPC-Web - API7.ai"
description: "gRPC Web Введение Изначально разработанный Google, gRPC — это высокопроизводительный удаленный ..."
url: "https://api7.ai/ru/blog/integration-with-grpc-web"
---

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

[Products](https://api7.ai/ru/category/products)[Technology](https://api7.ai/ru/category/technology)[Ecosystem](https://api7.ai/ru/category/ecosystem)[Case Study](https://api7.ai/ru/category/usercase)[Team & Community](https://api7.ai/ru/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, веб-приложения не могут использовать gRPC напрямую. gRPC Web — это стандартизированный протокол, который решает эту проблему.

Первая реализация gRPC-web была выпущена в 2018 году в виде библиотеки JavaScript, через которую веб-приложения могут напрямую взаимодействовать с gRPC-сервисом. Принцип работы заключается в создании сквозного gRPC-конвейера, совместимого с HTTP/1.1 и HTTP/2. Браузер отправляет обычный HTTP-запрос, а gRPC-Web прокси, расположенный между браузером и сервером, преобразует запрос и ответ. Подобно gRPC, gRPC Web использует предопределённый контракт между веб-клиентом и серверной gRPC-службой. Для сериализации и кодирования сообщений используются Protocol Buffers.

![Как работает gRPC-web](https://static.api7.ai/2022/10/03/633a423516b37.png?imageMogr2/format/webp)

С помощью gRPC Web пользователи могут напрямую вызывать серверные gRPC-приложения через браузер или Node-клиент. Однако при использовании gRPC-Web на стороне браузера для вызова gRPC-сервисов существуют некоторые ограничения.

- Не поддерживаются потоковые вызовы на стороне клиента и двунаправленные потоковые вызовы.
- Для вызова gRPC-сервисов через домены необходимо настроить CORS на стороне сервера.
- Серверная часть gRPC должна быть настроена для поддержки gRPC-Web, или должен быть доступен сторонний сервисный агент для преобразования вызова между браузером и сервером.

## Прокси gRPC Web в Apache APISIX

Apache APISIX поддерживает проксирование протокола gRPC Web с помощью плагина, который выполняет преобразование протокола и кодирование данных при взаимодействии gRPC Web с gRPC Server в плагине `grpc-web`. Процесс взаимодействия выглядит следующим образом.

gRPC Web Client -> Apache APISIX (преобразование протокола и кодирование данных) -> gRPC сервер

Ниже приведён полный пример, демонстрирующий, как создать gRPC Web Client и проксировать запросы gRPC Web через Apache APISIX. В этом примере мы будем использовать Go в качестве обработчика серверной части gRPC Server и Node в качестве клиента gRPC Web.

## Настройка Protocol Buffer

Первым шагом является установка компилятора Protocol Buffer и связанных плагинов.

1. Установите `protoc` и `proto-grpc-*`.

   Компилятор Protocol Buffer `protoc` и плагины `protoc-gen-go` и `protoc-gen-grpc-web` для генерации кода интерфейсов Go, JavaScript и gRPC Web для `.proto` должны быть установлены на вашей системе перед написанием клиентских и серверных приложений.

   Запустите следующий скрипт для установки вышеуказанных компонентов.

   ```
   #!/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. Создайте пример `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);
   }
   ```

## Настройка серверного приложения

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` код.

   Сгенерируйте клиентские JavaScript-сообщения, заглушки сервиса/клиента и код интерфейса для JavaScript gRPC Web.

   Плагин `proto` для gRPC Web предоставляет два режима генерации кода.

   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 Server и клиентское приложение gRPC Web, а также запустили серверное приложение, которое будет принимать запросы на порту `50001`.

## Настройка Apache APISIX

Далее просто включите плагин `grpc-web` в конфигурации плагинов маршрутизации Apache APISIX для проксирования запросов gRPC Web.

1. Включите плагин прокси `grpc-web`.

   Маршрутизация должна использовать **префиксное сопоставление** (например, `/* или /grpc/example/*`), так как gRPC Web клиент передаёт имя пакета, имя сервисного интерфейса, имя метода и т.д., объявленные в `proto`, в URI (например, `/path/a6.EchoService/Echo`). **Использование абсолютного сопоставления предотвратит извлечение информации `proto` из URI плагином**.

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

2. Проверка запросов прокси gRPC Web.

   Запрос по протоколу gRPC Web можно отправить в Apache APISIX, выполнив `client.js` из Node.

   Логика обработки на стороне клиента и сервера соответственно: клиент отправляет сообщение на сервер с содержимым `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
           }
       }
   }'
   ```

## Заключение

Эта статья предоставляет вам практический опыт использования `grpc-web` в Apache APISIX.

Не стесняйтесь начать обсуждение в [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 Gateway](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 Gateway](https://api7.ai/blog/why-do-microservices-need-an-api-gateway)

[![Зачем вам нужен Apache APISIX при использовании Amazon Lambda](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)

## [Зачем вам нужен Apache APISIX при использовании Amazon Lambda](https://api7.ai/blog/why-do-you-need-apache-apisix-when-using-amazon-lambda)

Table of Contents

- [Введение в gRPC Web](#%D0%B2%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B2-grpc-web)
- [Прокси gRPC Web в Apache APISIX](#%D0%BF%D1%80%D0%BE%D0%BA%D1%81%D0%B8-grpc-web-%D0%B2-apache-apisix)
- [Настройка Protocol Buffer](#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-protocol-buffer)
- [Настройка серверного приложения](#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F)
- [Настройка клиентских программ](#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D1%81%D0%BA%D0%B8%D1%85-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC)
- [Настройка Apache APISIX](#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-apache-apisix)
- [Заключение](#%D0%B7%D0%B0%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5)

## Related Posts

[![Раскрытие индивидуальных решений: использование Apache APISIX и Node-RED в гармонии](https://static.api7.ai/uploads/2024/03/06/uppjizMq_APISIX-node-red-cover.png)](https://api7.ai/ru/blog/apache-apisix-and-node-red)

Ecosystem

March 6, 2024

#### [Раскрытие индивидуальных решений: использование Apache APISIX и Node-RED в гармонии](https://api7.ai/ru/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/ru/blog/waf-and-api-gateway-integration)

Ecosystem

January 30, 2024

#### [Защита ваших API в дикой природе: глубокое погружение в интеграцию WAF и API Gateway](https://api7.ai/ru/blog/waf-and-api-gateway-integration)

Следуя лучшим практикам и используя правильные инструменты, вы можете создать надежный уровень безопасности, который защитит ваши API от широкого спектра атак.

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

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

[![mTLS повсюду: Как настроить TLS для APISIX](https://static.api7.ai/uploads/2024/12/24/DVhnbLpy_apisix-mtls.png)](https://api7.ai/ru/blog/configure-tls-for-apisix)

Ecosystem

July 31, 2023

#### [mTLS повсюду: Как настроить TLS для APISIX](https://api7.ai/ru/blog/configure-tls-for-apisix)

Transport Secure Layer, также известный как TLS, ранее называвшийся SSL, является одной из ключевых опор безопасности информационных систем. Давайте узнаем, как настроить TLS для API-шлюза Apache APISIX.

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

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