Почему мы переходим на gRPC

задняя часть внешний интерфейс Программа перевода самородков gRPC

Если вы используете архитектуру микросервисов, вам необходимо принять одно из фундаментальных решений: как сервисы должны обмениваться информацией? Подход по умолчанию, по-видимому, заключается в использовании протокола HTTP для отправки сообщений JSON — так называемого REST API, но большинство людей не воспринимают принципы REST всерьез. FromAtoB с использованием REST API — это то, с чего мы начали, однако недавно мы решили сделать gRPC нашим новым стандартом.

gRPCЭто система удаленного вызова процедур, разработанная Google и имеющая открытый исходный код. Хотя он существует уже много лет, я не нашел в Интернете никакой информации о том, почему люди используют его или нет, поэтому я решил написать статью, объясняющую, почему мы выбрали gRPC.

Самым большим преимуществом gRPC является то, что он использует эффективное двоичное кодирование, что делает его намного быстрее, чем JSON/HTTP. Хотя более высокие скорости часто приветствуются, здесь есть еще два важных аспекта: четкая спецификация интерфейса и поддержка потоков.

Спецификация интерфейса gRPC

При создании новой службы gRPC первым шагом обычно является.protoИнтерфейс определяется в файле. Следующий код.protoОбщий формат файла - это упрощенная версия небольшой части нашего собственного API. В этом примере определен удаленный вызов процедуры «Поиск» вместе с ее входными и выходными типами.

syntax = "proto3";

package fromatob;

// FromAtoB 是 fromAtoB 后台 API 的简化版本。
service FromAtoB {
	rpc Lookup(LookupRequest) returns (Coordinate) {}
}

// LookupRequest 是按照名称查找城市坐标的请求
message LookupRequest {
	string name = 1;
}

// Coordinate 使用经度和纬度定义了地球上的坐标
message Coordinate {
  // Latitude 是坐标的纬度,范围是 [-90, 90]。
	double latitude = 1;

  // Longitude 是坐标的经度,范围是 [-180, 180]。
	double longitude = 2;
}

Используя этот файл, вы можете использоватьprotocКомпилятор генерирует клиентский и серверный код, и вы можете начать писать код, который предоставляет или использует API.

Итак, почему этот файл дает нам преимущество, а не лишнюю работу? Давайте еще раз посмотрим на пример кода выше. Даже если вы никогда не использовали gRPC или Protocol Buffers, этот код очень удобочитаем: например, легко увидеть, что если вы хотите отправитьLookupзапрос, вы должны отправить строку типаnameпараметр, этот запрос вернет вамCoordinateрезультат типа, который содержит параметрыlatitudeиlongitude. На самом деле, как только вы добавите несколько простых аннотаций, как в примере,.protoЗатем этот файл может служить документацией API для вашего сервиса.

Конечно, реальная спецификация сервиса должна быть намного больше, но не сложнее. просто будет больше для методаrpcобъявления и для типовmessageутверждение.

пройти черезprotocСгенерированный код также гарантирует, что данные, отправляемые клиентом или сервером, соответствуют спецификации. Это очень полезно для отладки. Дважды, как я помню, служба, которую я поддерживал, генерировала данные JSON в неправильном формате, и поскольку формат не был проверен, ошибка появлялась только в пользовательском интерфейсе. Единственный способ найти ошибки — это отладить интерфейсный код JavaScript, что непросто для бэкенд-разработчика, который никогда не использовал интерфейсный JavaScript-фреймворк!

Swagger / OpenAPI

В принципе, если вы используете как HTTP/JSON API, так иSwaggerили его преемникOpenAPI, вы также можете получить такое же преимущество. Следующий пример кода также сопоставим с gRPC API:

openapi: 3.0.0

info:
  title: A simplified version of fromAtoB’s backend API
  version: '1.0'

paths:
  /lookup:
    get:
      description: Look up the coordinates for a city by name.
      parameters:
        - in: query
          name: name
          schema:
            type: string
          description: City name.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Coordinate'
        '404':
          description: Not Found
          content:
            text/plain:
              schema:
                type: string

components:
  schemas:
    Coordinate:
      type: object
      description: A Coordinate identifies a location on Earth by latitude and longitude.
      properties:
        latitude:
          type: number
          description: Latitude is the degrees latitude of the location, in the range [-90, 90].
        longitude:
          type: number
          description: Longitude is the degrees longitude of the location, in the range [-180, 180].

Сравните этот код со спецификацией gRPC. Появится код OpenAPIОченьТяжело читать! Он более подробный и сложный (восемь уровней отступов, в отличие от единственного в gRPC).

Аутентификация с помощью спецификации OpenAPI также намного сложнее, чем gRPC. По крайней мере, для внутренних сервисов все это означает, что спецификации либо не написаны, либо по мере итерации API становятся бесполезными, так как не обновляются.

поток

Ранее в этом году я начал разрабатывать новый API для нашей поисковой системы (представьте, что я ищу «пожалуйста, дайте мне все маршруты из Берлина в Париж на 1 июня 2019 года»). После того, как я создал первую версию API с использованием HTTP и JSON, мой коллега указал, что в некоторых случаях мне нужны результаты потокового запроса, а это означает, что, когда я получаю первый результат запроса, я должен снова начать отправлять эти результаты. Разработанный мной API просто возвращает простой массив JSON, поэтому служба не может отправлять запросы, пока не будут получены все результаты.

Использование такого API на внешнем интерфейсе требует, чтобы клиент инициировал запрос на опрос для получения результатов. Внешний интерфейс отправляет запросы POST для установки критериев поиска, а затем повторно отправляет запросы GET для получения результатов. Возвращаемые результаты будут содержать поле, подтверждающее завершение поиска. Это прекрасно работает, но не элегантно и требует, чтобы сервер использовал хранилище данных, такое как Redis, для кэширования промежуточных результатов. Новый API может быть реализован большим количеством более мелких сервисов, и я не хочу заставлять их всех реализовывать такую ​​логику.

Итак, мы решили попробовать gRPC. Если вы хотите отправить результат удаленного вызова, используя gRPC, вам просто нужноstreamдобавить ключевые слова в.protoв файле. ЭтоSearchОпределение функции:

rpc Search (SearchRequest) returns (stream Trip) {}

protocКод, сгенерированный компилятором, содержитSendОбъект функций, которые наш сервисный код будет вызывать для отправки по однойTripобъект, а также содержитRecvОбъект функции, которую клиентский код будет вызывать для получения результата. С точки зрения разработчика это проще, чем опрос приложений.полно.

Меры предосторожности

Также я хотел бы отметить, что gRPC также имеет некоторые недостатки. Все они касаются инструмента, а не самого протокола.

Когда вы создаете свой API с помощью HTTP/JSON, вы можете использовать curl, httpie или Postman для простого тестирования. Аналогичные инструменты есть и для gRPC, а именноgrpcurl, но с gRPC все не так гладко: нужно добавитьСопоставление службы gRPCрасширение или указать в каждой команде соответствующий.protoдокумент. Мы подумали, что будет проще добавить небольшой инструмент командной строки на стороне сервера, который может отправлять простые запросы. иprotocСгенерированный клиентский код уже делает отправку запросов очень простой.

Еще одна большая проблема — балансировка нагрузки Kubernetes. Балансировка нагрузки, которую мы использовали для HTTP-сервисов, не очень подходит для gRPC. По сути, балансировка нагрузки, необходимая для gRPC, осуществляется на уровне приложения, а не на уровне соединения TCP. Чтобы решить эту проблему, мы обращаемся к учебнику:gRPC Load Balancing on Kubernetes without Tears,созданныйLinkerd.

Суммировать

Хотя для создания gRPC API потребуется дополнительная предварительная работа, мы обнаружили, что преимущества наличия четкой спецификации API и поддержки потоковой передачи более чем компенсируют предварительную работу. Для нас gRPC будет выбором по умолчанию для всех новых внутренних сервисов, которые мы будем создавать.

Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллекти другие поля, если вы хотите видеть больше качественных переводов, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.