Использование gRPC с Python

Микросервисы теперь являются предпочтительной архитектурой для многих разработчиков при создании облачных приложений. Приложение микросервисов — это набор слабосвязанных сервисов, которые взаимодействуют друг с другом, улучшая совместную работу, удобство обслуживания, масштабируемость и развертывание. Существует несколько вариантов включения такого взаимодействия между микросервисами. REST — самый популярный среди разработчиков, иногда используемый как синоним API. Однако gRPC может быть лучшей альтернативой REST. В этом уроке вы познакомитесь с основами gRPC и узнаете, как начать работу с ним с использованием Python.

Что такое gRPC?

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

Лендинг-2.svg

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

Зачем использовать gRPC?

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

Вот некоторые преимущества, которые предлагает gRPC:

Language Agnostic

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

Улучшенная потоковая передача

gRPC имеет мощную поддержку потоковой передачи клиента, потоковой передачи сервера и двунаправленной потоковой передачи, и его проще реализовать по сравнению с REST.

Лучшая скорость

gRPC обеспечивает более высокую скорость, чем REST, GraphQL и SOAP, поскольку для сериализации данных он использует буферы протокола вместо JSON или XML. Это делает полезную нагрузку меньше и быстрее.

Генерация кода

Используя протокольный компилятор или компилятор буферов протоколов, вы можете легко скомпилировать .proto файлы в код, специфичный для конкретного языка. Это упрощает процесс создания службы API и клиентских библиотек.

Начало работы с gRPC в Python

Теперь, когда вы знаете больше о gRPC, вы увидите его в действии. Из этого руководства вы узнаете, как создать простой сервис API и клиент, который получает цены на криптовалюты в режиме реального времени.

Предварительные условия

Чтобы следовать этому руководству, вам потребуются следующие зависимости:

Установка зависимостей

Используйте следующие команды для установки зависимостей на ваш компьютер:

# Create a directory for the project
mkdir crypto-service
cd crypto-service

# Create a virtual environment

virtualenv crypto

# For those in Windows

crypto/Scripts/activate
pip install grpcio grpcio-tools

# For those in Linux and MacOS

source crypto/bin/activate 
pip3 install grpcio grpcio-tools

Создание рабочего процесса

Когда вы создаете службы API и клиенты с помощью gRPC, вы обычно следуете следующему рабочему процессу:

  • Определите службы и сообщения в .protoфайлах.
  • Скомпилируйте .proto файл(ы) для кодирования артефактов.
  • Используйте сгенерированные артефакты кода для реализации кода сервера и кода клиента.

Основы протокольного буфера

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

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

Такой сервис в gRPC должен выглядеть примерно так:

Чтобы создать это в gRPC, создайте новый .proto файл, как показано ниже:

touch crypto_service.proto

Вот как будет выглядеть определение буфера протокола. Скопируйте и вставьте приведенный ниже код в crypto_service.proto созданный вами файл:

syntax = "proto3";

// Incoming request from client
message cryptocurrency{
   optional string name = 1;
}

// Response to be returned by API service
message market_price{
   optional float max_price = 1;
   optional float min_price = 2;
   optional float avg_price = 3;
}

// Service definition for GExchange
service GExchange {

   // get_price method definition
   rpc get_price (cryptocurrency) returns (market_price) {};

}

Компиляция с помощью протокола

Теперь у вас есть определение протобуфера для криптосервиса. Следующий шаг — использование компилятора protoc для компиляции crypto_service.proto файла для кодирования артефактов. Для этого вы можете использовать одну команду через терминал (или командную строку для пользователей Windows), как показано ниже:

python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. crypto_service.proto

Когда вы запустите приведенную выше команду, она сгенерирует два файла Python с crypto_service.protoименами:

  • crypto_service_pb2.py
  • crypto_service_pb2_grpc.py

Вы можете просмотреть содержимое файлов, но не беспокойтесь о них, потому что вы не собираетесь их редактировать. Если вы отметите crypto_service_pb2_grpc.py, вы заметите, что созданы три класса, два из которых — GExchangeServicerи GExchangeStub. Вы собираетесь использовать их для реализации серверного и клиентского кода соответственно.

Реализация gRPC-сервера

Далее вы собираетесь реализовать сервер gRPC из сгенерированных артефактов и создать новый файл Python в том же каталоге под названием crypto_server.py.

touch crypto_server.py

Вам нужно будет сначала импортировать все необходимые требования, а затем создать класс, который будет наследовать GExchangeServicer. Его методы будут иметь то же имя, что определено в crypto_service.protoфайле. Для этого урока имя get_price показано ниже:

import grpc
from concurrent import futures
import crypto_service_pb2 as pb2
import crypto_service_pb2_grpc as pb2_grpc

# A class for handling GExchange service
class GExchange(pb2_grpc.GExchangeServicer):
   def get_price(self, request, context):
       return pb2.market_price(**data.get(request.name, {}))

Единственное, что необходимо для вашего gRPC-сервера, — это инструкция для вашего сервиса и исходные фиктивные данные для запроса. Вы собираетесь использовать встроенную функцию Python futures, gRPC library с некоторыми компонентами из сгенерированных артефактов, чтобы проинструктировать свой код Python о том, как запускать GExchangeслужбу. Как только вы их добавите, ваш код должен выглядеть следующим образом:

import grpc
from concurrent import futures
import crypto_service_pb2 as pb2
import crypto_service_pb2_grpc as pb2_grpc

class GExchange(pb2_grpc.GExchangeServicer):
   def get_price(self, request, context):
       return pb2.market_price(**data.get(request.name, {}))

def serve():
   server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
   pb2_grpc.add_GExchangeServicer_to_server(GExchange(), server)
   server.add_insecure_port("[::]:50051")
   server.start()
   server.wait_for_termination()

data = {
   "Ethereum": {"max_price": 4000.0, "min_price": 3590.0, "avg_price": 3800.0},
   "Bitcoin": {"max_price": 50000.0, "min_price": 48539.0, "avg_price": 49072.0},
   "Cardano": {"max_price": 3.3, "min_price": 2.9, "avg_price": 3.12},
}

if __name__ == "__main__":
   print("running the gRPC server")
   serve()

Теперь вы можете запустить службу gRPC так же, как обычно запускаете сценарий Python, как показано ниже:

python3 crypto_server.py
.....
running the gRPC server

Реализация клиента gRPC

В этом разделе вы узнаете, как реализовать клиент gRPC на Python. Сначала создайте новый файл Python, fetch_prices.py.

# creates a new file
touch fetch_prices.py

Импортируйте все необходимые библиотеки, а затем создайте класс для своего клиента. В конструкторе класса создайте заглушку или клиент, который будет подключаться к gRPC. Вот как это сделать:

import grpc
import crypto_service_pb2 as pb2
import crypto_service_pb2_grpc as pb2_grpc

class fetchPrices(object):
   def __init__(self):
       # creates a gRPC channel to connect to a server
       self.channel = grpc.insecure_channel("localhost:50051")
       # creates a gRPC stub(client) to communicate to server
       self.stub = pb2_grpc.GExchangeStub(self.channel)

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

import grpc
import crypto_service_pb2 as pb2
import crypto_service_pb2_grpc as pb2_grpc

class fetchPrices(object):
   def __init__(self):
       self.channel = grpc.insecure_channel("localhost:50051")
       self.stub = pb2_grpc.GExchangeStub(self.channel)

   def get_price(self, name):
       request = pb2.cryptocurrency(name=name)
       response = self.stub.get_price(request)
       return response

if __name__ == "__main__":
   client = fetchPrices()
   print(client.get_price("Bitcoin"))
   print(client.get_price("Ethereum"))
   print(client.get_price("Cardano"))

Ваш сервер gRPC уже должен быть запущен. Если нет, сначала запустите его; в противном случае ваши клиентские сценарии вызовут исключение. Как только вы это сделаете, вы готовы к работе.

Теперь запустите ваш fetch_prices.py скрипт:

python3 fetch_prices.py
........
max_price: 50000.0
min_price: 48539.0
avg_price: 49072.0

max_price: 4000.0
min_price: 3590.0
avg_price: 3800.0

max_price: 3.299999952316284
min_price: 2.9000000953674316
avg_price: 3.119999885559082

После запуска ваш сценарий должен иметь возможность эффективно взаимодействовать с сервером gRPC, а ответ должен выглядеть так, как показано выше, поскольку вы использовали тот же пример для данных.

Заключение

Теперь вы должны лучше понимать gRPC и то, как его использовать в качестве разработчика Python. В этом руководстве продемонстрированы унарные RPC, в которых клиент отправляет один запрос серверу и получает обратно один ответ. Существует несколько типов реализации gRPC, и сегодняшнее упражнение — это только начало того, чему вы можете научиться.

Использование gRPC может обеспечить более высокую производительность и большую гибкость для связи между вашими микросервисами.