Знакомство с качественной связью gRPC, с ней кто еще использует Socket

алгоритм
Знакомство с качественной связью gRPC, с ней кто еще использует Socket

Это 12-й день моего участия в ноябрьском испытании обновлений. Узнайте подробности события:Вызов последнего обновления 2021 г.

1 Значение

Платформа RPC (удаленный вызов процедур) фактически предоставляет механизм, который обеспечивает связь между приложениями, а также следует модели сервер/клиент. При его использовании клиентская сторона вызывает интерфейс, предоставленный серверной стороной, точно так же, как вызов локальной функции.

gRPC — это высокопроизводительная универсальная среда RPC с открытым исходным кодом, разработанная для мобильных устройств и HTTP/2. В настоящее время предоставляются языковые версии C, Java и Go, а именно: grpc, grpc-java, grpc-go.Версия C поддерживает поддержку C, C++, Node.js, Python, Ruby, Objective-C, PHP и C#.

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

2 Определите услугу

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

service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  required string greeting = 1;
}

message HelloResponse {
  required string reply = 1;
}

2.1 Четыре способа определения услуг

2.1.1 Один RPC

  • Клиент отправляет запрос на сервер и получает ответ от сервера, как при обычном вызове функции.
rpc SayHello(HelloRequest) returns (HelloResponse){
}

2.1.2 Потоковая RPC на стороне сервера

  • Клиент отправляет запрос на сервер, чтобы получить поток данных для чтения серии сообщений. Клиент читает из возвращенного потока данных до тех пор, пока не останется сообщений.
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}

2.1.3 Клиентская потоковая передача RPC

  • Клиент пишет и отправляет серию сообщений на сервер, используя предоставленный поток данных. Как только клиент заканчивает писать сообщения, он ждет, пока сервер прочитает сообщения и вернет ответ.
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}

2.1.4 Двунаправленный потоковый RPC

  • Обе стороны могут отправлять серию сообщений через поток данных чтения и записи соответственно. Операции с двумя потоками данных независимы друг от друга, поэтому клиент и сервер могут читать и записывать в любом порядке, который они хотят, например: сервер может ждать всех клиентских сообщений, прежде чем писать ответ, или он может сначала прочитать сообщение Записать другое сообщение или какое-либо другое сочетание чтения и записи. Порядок сообщений в каждом потоке данных сохраняется.
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}

2.1.5 Использование интерфейса API

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

  • На стороне сервера сервер реализует интерфейс службы и запускает сервер gRPC для обработки клиентских вызовов. Базовая архитектура gRPC декодирует входящие запросы, выполняет методы службы и кодирует ответы службы.
  • На стороне клиента у клиента естьзаглушкаРеализован тот же метод на стороне сервера. Клиенты могут вызывать эти методы в локальной заглушке, упаковывая параметры в соответствующий тип сообщения буфера протокола — gRPC отвечает за отправку запроса на сервер и возврат ответа буфера протокола сервера.

2.1.6 Синхронный и асинхронный

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

На большинстве языков интерфейс программирования gRPC поддерживает как синхронные, так и асинхронные функции. Вы можете найти дополнительную информацию в каждом учебнике по языку и справочной документации (полная документация скоро появится).

2.2 Жизненный цикл КПК

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

2.2.1 Один RPC

Сначала давайте рассмотрим простейшую форму RPC: клиент делает один запрос и получает один ответ.

  • Как только клиент вызывает метод через заглушку, сервер будет уведомлен об этом, включая метаданные клиента, имя метода и разрешенный период ответа (если применимо).
  • Сервер может либо отправить исходные метаданные непосредственно перед любым ответом, либо дождаться информации о запросе клиента, в зависимости от того, что произойдет раньше, зависит от конкретного приложения.
  • Как только сервер получает информацию о запросе клиента, он выполняет всю работу, необходимую для создания или сборки соответствующего ответа. В случае успеха ответ возвращается клиенту с информацией о состоянии, включая код состояния и дополнительную информацию о состоянии и дополнительную информацию об отслеживании.
  • Если статус в порядке, клиент получит ответ, который завершит вызов клиента.

2.2.2 Потоковая RPC на стороне сервера

Потоковая передача RPC на стороне сервера аналогична нашему простому примеру, за исключением того, что она отправляет обратно поток ответов после получения информации из запроса клиента. После отправки всех ответов сведения о состоянии сервера (код состояния и необязательная информация о состоянии) и необязательные метаданные отслеживания отправляются обратно клиенту для завершения работы сервера. Клиент также завершает работу после получения всех ответов от сервера.

2.2.3 Клиентский поток RPC

Потоковая RPC на стороне клиента в основном такая же, как и в нашем простом примере, за исключением того, что клиент отправляет поток запросов на сервер вместо одного запроса. Сервер обычно (но не обязательно) отправляет ответ после получения всех запросов клиента вместе со сведениями о своем статусе и необязательными данными трассировки.

2.2.4 Двунаправленный потоковый RPC

Двусторонняя потоковая RPC, вызов инициируется клиентом, вызывающим метод, и сервер получает метаданные клиента, имя метода и крайний срок. Сервер может отправить обратно свои исходные метаданные или подождать, пока клиент отправит запрос. Что будет дальше, зависит от приложения, потому что клиент и сервер могут читать и записывать в любом порядке — операции с этими потоками полностью независимы. Например, сервер может подождать, пока он получит все сообщения клиента, прежде чем написать ответ, или сервер и клиент могут быть похожи на «шарики для пинг-понга»: после того, как сервер получит запрос, он отправляет ответ, а затем клиент отправляет в соответствии с ответом, другой запрос и т.д.

2.2.5 Крайний срок

gRPC позволяет клиентам указывать крайний срок перед вызовом удаленного метода. Это значение указывает, как долго клиент может ждать ответа сервера, после чего RPC завершится и вернется.DEADLINE_EXCEEDEDОшибка. Значение срока действия можно запросить на сервере, чтобы узнать, истек ли срок действия конкретного метода или сколько времени осталось для завершения метода. То, как каждый язык указывает крайний срок, различается — например, в Python всегда требуется значение крайнего срока, но не во всех языках есть крайний срок по умолчанию.

2.2.6 Завершение RPC

В gRPC клиент и сервер оценивают успешность вызова независимо и локально, и их выводы могут быть противоречивыми. Это означает, что, например, если у вас есть RPC, который успешно завершается на сервере («Я вернул все ответы!»), он может к этому времени дать сбой на клиенте («Ответы пришли после крайнего срока!») . Также возможно, что сервер определяет, что вызов был завершен до того, как клиент отправил все запросы.

2.2.7 Отмена RPC

Либо клиент, либо сервер могут отменить RPC в любое время. Отмена немедленно завершает RPC, так что дальнейшие операции не выполняются. Этонет«Отмена», которая была завершена до отмены, не будет отменена. Конечно, синхронно вызванный RPC нельзя отменить, поскольку управление программой не возвращается к приложению до тех пор, пока RPC не завершится.

2.2.8 Набор метаданных

Метаданные — это информация, соответствующая специальному RPC-вызову.Эта информация существует в виде пар ключ-значение.Как правило, тип ключа — строка, а тип значения — строка (конечно, может также быть двоичными данными). Метаданные непрозрачны для самого gRPC — они позволяют клиенту предоставлять серверу информацию о звонках и наоборот. Доступ к метаданным зависит от языка.

2.2.9 Каналы

При создании клиентской заглушки канал gRPC обеспечивает подключение к серверу на определенном хосте и порту. Клиенты могут изменить поведение gRPC по умолчанию, указав параметры канала, такие как включение и отключение сжатия сообщений. Канал имеет состояние, содержащее已连接и空闲. То, как gRPC обрабатывает закрытие канала, зависит от языка. Некоторые языки позволяют запрашивать статус канала.

3 преимущества gRPC:

  • gRPC может определять интерфейсы через protobuf, чтобы иметь более строгие ограничения интерфейса. О protobuf см. предыдущую статью автора.Краткое руководство по Google Protobuf
  • Кроме того, данные можно сериализовать в двоичное кодирование с помощью protobuf, что значительно уменьшает объем данных, которые необходимо передать, тем самым значительно повышая производительность.
  • gRPC может легко поддерживать потоковую связь (теоретически, потоковый режим можно использовать через http2.0, но обычно restful API веб-сервисов, по-видимому, редко используется таким образом, а обычные приложения для потоковой передачи данных, такие как потоковое видео, обычно используют специальные протоколы типа HLS, RTMP и т.д., это не привычные нам веб-сервисы, а специальные серверные приложения.)

4 сценария использования

  • Требуются строгие ограничения на интерфейс.Например, мы предоставляем общедоступную услугу, и многие люди, даже люди за пределами компании, могут получить доступ к услуге.В настоящее время мы надеемся иметь более строгие ограничения на интерфейс, и мы не хотим, чтобы клиент дал Мы передаем произвольные данные, особенно учитывая фактор безопасности, нам обычно нужно накладывать более строгие ограничения на интерфейс. В настоящее время gRPC может обеспечить строгие ограничения интерфейса через protobuf.
  • Когда есть повышенные требования к производительности. Иногда нашему сервису необходимо передать большой объем данных, не влияя на нашу производительность.В это время мы также можем рассмотреть сервис gRPC, потому что через protobuf мы можем преобразовать кодировку со сжатием данных в двоичный формат, а объем передаваемых данных обычно намного меньше ., а через http2 мы можем реализовать асинхронные запросы, что значительно повышает эффективность связи.

Однако обычно мы не используем gRPC отдельно, а используем gRPC как компонент, потому что в производственной среде, когда мы сталкиваемся с большим параллелизмом, нам нужно использовать распределенную систему для его обработки, а gRPC не предоставляет некоторых необходимых компонентов. относится к распределенным системам. Кроме того, настоящий онлайн-сервис также должен предоставлять необходимые компоненты, включая балансировку нагрузки, ограничение тока и плавкие переходы, мониторинг и аварийную сигнализацию, регистрацию и обнаружение службы и т. д. Однако это не тема данной статьи, давайте продолжим смотреть, как использовать gRPC.

5 примеров начала работы

На этот раз попробуйте код Python для реализации случая входа Hello World. Использование gRPC обычно включает следующие шаги:

  1. Определение интерфейсов и типов данных через protobuf
  2. Написать серверный код gRPC
  3. Написать клиентский код gRPC

Каталог всего проекта выглядит следующим образом:

image-20210903182117597

5.1 Настройка среды gRPC

Различные операционные системы настраивают среду по-разному, в этот раз я попробовал среду win10. Сначала объясните, как настроить метод в среде win10.

5.1.1 Установка Protobuf

Выполнить под Ubuntu:

pip install protobuf    # 安装protobuf库
sudo apt-get install protobuf-compiler  # 安装protobuf编译器

Под Win10:

Войдите на официальный сайт:адрес, выберите версию win64-bit.

image-20210903180930853

Затем в переменной среды разархивируйте скачанный файл, а затем пропишите каталог в переменную среды. Мой находится в C:\protoc-3.17.3-win64\bin.

image-20210903181319481

Затем выполните в CMD: protoc --version.

image-20210903181519056

На этом настройка среды завершена, а затем выполните:

pip install protobuf    # 安装protobuf库

Установите библиотеку python для protobuf.

5.1.2 Установите библиотеку инструментов gprc

pip install grpcio-tools

5.1.3 Определение интерфейса

Определить интерфейсы и типы данных через protobuf. Создайте новую папку protos, введите новый файл helloworld.proto и добавьте следующее содержимое:

syntax = "proto3";
package rpc_package;
// define a service
service HelloWorldService {
    // define the interface and data type
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// define the data type of request
message HelloRequest {
    string name = 1;
}
// define the data type of response
message HelloReply {
    string message = 1;
}

Создайте новую папку rpc_package, а затем используйте средство создания gRPC protobuf для создания библиотечных функций на соответствующем языке. Результирующий каталог указывается в папке rpc_package.

python -m grpc_tools.protoc -I=./protos --python_out=./rpc_package --grpc_python_out=./rpc_package ./protos/helloworld.proto

Создайте: helloworld_pb2.py и helloworld_pb2_grpc.py два файла.

Создайте _ в папке rpc_packageinit_.py измените пятое поведение helloworld_pb2_grpc.py:

import rpc_package.helloworld_pb2 as helloworld__pb2

В противном случае возникнет проблема, что библиотеку невозможно найти.

5.2 Код на стороне сервера и код на стороне клиента

hello_server.py

#!/usr/bin/env python
# -*-coding: utf-8 -*-

from concurrent import futures
import grpc
import logging
import time
from rpc_package.helloworld_pb2_grpc import add_HelloWorldServiceServicer_to_server,HelloWorldServiceServicer
from rpc_package.helloworld_pb2 import HelloRequest, HelloReply


class Hello(HelloWorldServiceServicer):

    # 这里实现我们定义的接口
    def SayHello(self, request, context):
        return HelloReply(message='Hello, %s!' % request.name)


def serve():
    # 这里通过thread pool来并发处理server的任务
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

    # 将对应的任务处理函数添加到rpc server中
    add_HelloWorldServiceServicer_to_server(Hello(), server)

    # 这里使用的非安全接口,世界gRPC支持TLS/SSL安全连接,以及各种鉴权机制
    server.add_insecure_port('[::]:50000')
    server.start()
    try:
        while True:
            time.sleep(60 * 60 * 24)
    except KeyboardInterrupt:
        server.stop(0)


if __name__ == "__main__":
    logging.basicConfig()
    serve()

hello_client.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
import logging

import grpc
from rpc_package.helloworld_pb2 import HelloRequest, HelloReply
from rpc_package.helloworld_pb2_grpc import HelloWorldServiceStub

def run():
    # 使用with语法保证channel自动close
    with grpc.insecure_channel('localhost:50000') as channel:
        # 客户端通过stub来实现rpc通信
        stub = HelloWorldServiceStub(channel)
        # 客户端必须使用定义好的类型,这里是HelloRequest类型
        response = stub.SayHello(HelloRequest(name='AI浩'))
    print ("hello client received: " + response.message)

if __name__ == "__main__":
    logging.basicConfig()
    run()

5.3 Бег

Сначала выполните серверный код

python hello_server.py

Затем выполните клиентскую часть

python hello_client.py

результат операции:

hello client received: Hello, AI浩!

Справочная статья:

Подробное объяснение gRPC — краткая книга (jianshu.com)