GRPC vs REST

2024-08-16T20:36:24+05:00 | 3 минуты чтения | Обновлено 2024-08-17T12:37:37+05:00

Что такое GRPC и зачем он если есть REST?

GRPC - это еще один способ обмена данными между сервисами. Он быстрее и эффективнее чем REST. Далее будет пример как сделать обмен данными между клиентом на Python и сервером Golang используя GRPC.

Пример REST API

Представьте сервер который по ID пользователя возвращает его имя и email. Если бы мы использовали REST, то клиент должен был сделать GET запрос:

GET https://localhost/user/<ID>

И получил бы в ответ какой-то JSON

{
  "id": 1,
  "name": "foo",
  "email": "foo@localhost"
}

Что нужно сделать чтобы такая схема заработала?

Сделать сервер:

package main

import (
	"net/http"

	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()
	e.GET("/user/:id", func(c echo.Context) error {
		return c.JSON(http.StatusOK,
			struct {
				ID    string
				Name  string
				Email string
			}{
				c.Param("id"),
				"foo",
				"foo@localhost",
			})
	})
	e.Logger.Fatal(e.Start(":8081"))
}

Написать клиент:

import requests
response = requests.get('http://localhost:8081/user/1')
print(response)

В случае GRPC все не так просто, но этого способа обмена есть много плюсов о которых сказано в конце.

Пример GRPC

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

syntax = "proto3";
option go_package="grpc-example/pb";

// Есть некий сервис User
service User {
  
  // У него есть функция Info которая 
  // принимает Request и возвращает Response
  rpc Info(Request) returns (Response) {}
}

// Описываем что принимает функция на вход
message Request {
  int32 ID = 1;
}

// А здесь описываем, что она возвращает
message Response {
  int32 ID = 1;
  string name = 2;
  string email = 3;
}

Этот файл формата protocol buffers который придумал Google. Для чего он придуман и какие у него есть плюсы это тема отдельной статьи.

Важно что в файле мы описываем сервисы, их функции и структуры которые являются параметрами этих функций.

Дальше при помощи специального компилятора из .proto файла можно сгенерировать код на Go, Python и еще куче языков программирования который в дальнейшем подключается как библиотека к нашему клиенту и серверу.

Выглядят команды запуска компилятора примерно так:

# Генерация кода на Go
protoc --go_out=. --go-grpc_out=. *.proto

# Для Python
python -m grpc_tools.protoc -Iexample --python_out=. --grpc_python_out=.

Важно понять, что в результате этих манипуляций мы получим сгенерированные библиотеки на go и python которые используем в своей работе.

Вот как это выглядит.

package main

import (
	"context"
	
	// Здесь подключим сгенерированную библиотеку
	"grpc-vs-rest/grpc-example/pb" 
	
	"log"
	"net"

	// Стандартная библиотека гугла для работы с GRPC
	"google.golang.org/grpc" 
)

// Создадим сервер
type UserServer struct {
	
	// Встраиваем структуру из 
	// сгенерированной библиотеки
	pb.UnimplementedUserServer
}

// Реализуем конкретную функцию
// нам не нужно ничего кодировать
// grpc все берет на себя
func (s UserServer) Info(_ context.Context, r *pb.Request) (*pb.Response, error) {
	resp := pb.Response{
		ID:    r.ID,
		Name:  "foo",
		Email: "foo@localhost",
	}
	return &resp, nil
}

func main() {
	lis, err := net.Listen("tcp", ":50005")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	server := grpc.NewServer()
	pb.RegisterUserServer(server, UserServer{})

	if err := server.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

Теперь клиент:

# dirty hack
import os
import sys
sys.path.append(os.getcwd() + '/pb')

import grpc
from pb import user_pb2, user_pb2_grpc

channel = grpc.insecure_channel('localhost:50005')
stub = user_pb2_grpc.UserStub(channel)

# Вот тут весь запрос к серверу
req = user_pb2.Request(ID=1)
req.ID = 1
response = stub.Info(req)

print(response)

Мы указываем адрес сервера и вызываем функцию сгенерированной библиотеки, всю остальную работу GRPC берет на себя.

Заключение

GRPC выглядит монструознее REST, нужно больше подготовительных операций.

Если у вас сервис с двумя эндпойтами, без высокой нагрузки, то GRPC не ваш выбор.

Но у GRPC много плюсов:

  • быстрее
  • потребляет меньше траффика
  • при большом количестве сервисов и обменов поддержка проще
  • возможны двусторонние обмены в потоковом режиме, но это тема отдельной статьи

Рабочий пример из статьи с замером времени https://github.com/pahanini/grpc-vs-rest

© 2022 - 2024 pahanini.com - записная книжка

🌱 Powered by Hugo with theme Dream.

О себе

Меня зовут Павел. Работаю в sima-land.ru

Отвечаю за большую часть ИТ инфраструктуры. Умею писать код, руководить людьми. Разбираюсь во многих аспектах ИТ: программирование, управление, архитектура.

Еще у меня много разных хобби не связанных с ИТ.

Этот сайт я использую как записную книжку. Может эта информация будет полезна кому-то еще.

Фото

Все фото на сайте мои и чаще никак не связаны с темой статьи.

Лицензия(Creative Commons)

Контент сайта лицензирован CC BY-NC-SA 4.0

All contents of this website are licensed under CC BY-NC-SA 4.0

Социальные сети