- PVSM.RU - https://www.pvsm.ru -

Twirp против gRPC. Стоит ли?

Если вы используете микро-сервисную архитектуру, то скорее всего знаете, что накладные расходы на коммуникацию между сервисами часто становятся значительной проблемой и если Вы сталкивались с этой проблемой, то скорее всего начали использовать Protobuf [1] и и его реализацию от Google gRPC [2] или Go-Kit [3] от Peter Bourgon или что-то другое. Пересказывать что это и как этим пользоваться нет смысла, все достаточно хорошо описано до меня. Я сам активно использую gRPC в своих проектах, но тут Twich [4] решил выпустить свою реализацию protobuf Twirp [5]. Если Вам интересно, зачем им это было нужно или чем она отличается проходите под кат.

Прежде всего давайте посмотрим на причины заставившие Twich релизить свою собственную версию ProtoBuf:

  • Отсутствие поддержки HTTP 1.1. gRPS опирается на HTTP-трейлеры и полно-дуплексные потоки (full-duplex streams). Twirp поддерживает и HTTP 1.1 и HTTP/2, что очень важно потому что большое количество load-balancer-ов (как хардварных, так и софтверных) поддерживают только HTTP 1.1 — включая AWS Elastic Load Balancer. Но в отличии от gRPC Twirp не поддерживает стримингового RPC [6], что в случае когда Ваш API построен по принципу Request-Response и не требуется.
  • Cложность реализации библиотеки grpc-go [7]. Библиотека включает полную реализации HTTP/2, независимую от стандартных библиотек, что делает сложным ее пониманию и анализ возникающих ошибок.
  • Cовместимость версий gRPC. В силу того, что gRPC довольно сложен, генерируемый Go код довольно простой и все запросы перенаправляются в grpc-go [7]. Такая связанность приводит к тому, что клиент вынужден использовать ту же самую версию, что и сервер. И если у Вас большое количество клиентов и сервис взаимодействую друг с другом, то версия между ними должна быть идентичная. Понятно, что это приводит к сложностям в деплойменте и развертыванию микросервисов.
  • Также Twitch указывают, что grpc-go требует определенную версию protobuf — github.com/golang/protobuf [8]. Но для меня эта проблема кажется надуманной, так как protobuf имеет только один релиз версии v1.0.0, который используется всеми версиями grpc-go.
  • gRPC поддерживает только бинарную форму сообщений и сниффинг сообщений очень сложным для анализа. Twirp поддерживает как бинарную форму сообщения в формате protobuf, так и в небинарные в формате JSON. Это вам дает преимущество, скажем если вы хотите взаимодействовать с сервисом через обычный HTTP Request посредством JSON

Как видите, простота это основновная причина, по которой Twich решили написать свою реализацию Protobuf.

Теперь давайте посмотрим, как же использовать эту библиотеку.

Если у вас уже настроена среда разработки на Go, то Вам нужно установить следующие пакеты

go get github.com/twitchtv/twirp/protoc-gen-twirp
go get github.com/golang/protobuf/protoc-gen-go

Для пример напишем простой сервис, который инкрементит значение переданное в качестве параметра.

syntax = "proto3";

service Service {
   rpc Increment(Request) returns (Response);
}

message Request {
   int32 valueToIncrement = 1; // must be > 0
}

message Response {
   int32 IncrementedValue = 1; // must be > 0
}

Сгенерируем код для нашего клиента выполнив следующую команду

protoc --proto_path=$GOPATH/src:. --twirp_out=. --go_out=. ./paperclips.proto

В результате буду созданы два файла

  • Increment.pb.go — содержит кодо-генерацию для сообщений
  • Increment.twirp.go — содержит интерфейсы и функции сервиса

Дальше добавим реализацию нашего сервиса

package main

import (
  "fmt"
  "log"
  "net/http"
  "context"
  pb "TwirpSample/Server/Twirp"
)

// Server implements the Increment service
type Server struct {
  value int32
}

// NewServer creates an instance of our server
func NewServer() *Server {
  return &Server{
     value: 1,
  }
}

// Increment returns the incremented value of request.ValueToIncrement
func (s *Server) Increment(ctx context.Context, request *pb.Request) (*pb.Response, error) {
  return &pb.Response{
     IncrementedValue: request.ValueToIncrement + 1,
  }, nil
}

func main() {
  fmt.Printf("Starting Increment Service on :6666")

  server := NewServer()
  twirpHandler := pb.NewServiceServer(server, nil)

  log.Fatal(http.ListenAndServe(":6666", twirpHandler))
}

Теперь, если вы запустите клиента командой go run main.goм к сервису можно будет обратиться как по HTTP:

curl --request "POST" 
     --location "http://localhost:6666/Service/Increment" 
     --header "Content-Type:application/json" 
     --data '{ValueToIncrement: 0}' 
     --verbose


Output:
{"IncrementedValue":1}

Или в бинарном формате

package main

import
  (
  "fmt"
  rpc "TwirpSample/Server/Twirp"
  "net/http"
  "context"
)

func main() {

  fmt.Println("Twirp Client Example.")

  client := rpc.NewServiceProtobufClient("http://localhost:6666", &http.Client{})
  v, err := client.Increment(context.Background(), &rpc.Request{ValueToIncrement: 11})

  if err != nil {
     fmt.Println(err.Error())
  }
  fmt.Printf("Value: %d", v.IncrementedValue)
}


Output:
Twirp Client Example.
Value:  11

В целом сам фреймворк практически идентичен по подходам с gRPC, но прост в реализации и с одновременной поддержкой HTTP 1.1. На мой взгляд его применимость, если вам необходим RPC сервис, с который вы планируем одновременно взаимодействовать с UI посредством HTTP и между сервисами посредством Protobuf.

Ссылки:

Автор: Valentyn Ponomarenko

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/golang/279188

Ссылки в тексте:

[1] Protobuf: https://developers.google.com/protocol-buffers/docs/proto3

[2] gRPC: https://github.com/google/protobuf

[3] Go-Kit: https://gokit.io/

[4] Twich: https://dev.twitch.tv/products

[5] Twirp: https://github.com/twitchtv/twirp

[6] стримингового RPC: http://guides/concepts.html#server-streaming-rpc

[7] grpc-go: https://github.com/grpc/grpc-go

[8] github.com/golang/protobuf: http://github.com/golang/protobuf

[9] Twirp:a sweet new RPC framework for Go: https://blog.twitch.tv/twirp-a-sweet-new-rpc-framework-for-go-5f2febbf35f

[10] Hacker News Twirp discussion: https://news.ycombinator.com/item?id=16162094

[11] Reddit Twirp discussion: https://www.reddit.com/r/golang/comments/7qvi0w/twirp_a_sweet_new_rpc_framework_for_go_twitch_blog/

[12] Источник: https://habr.com/post/354706/?utm_source=habrahabr&utm_medium=rss&utm_campaign=354706