Страницы

воскресенье, 29 октября 2017 г.

Going to gRPC

Недавно начал инвестигировать gRPC + Protocol Buffers. В Node.js профит сомнительный, по крайней мере до тех пор пока не появится стабильный http/2 (без флага --expose-http2), тем не менее никто не мешает уже сейчас использовать другую платформу, я бы предпочел Go. Первое знакомство с Node.js прошло без проблем, а вот с Go пришлось повозиться: скачать C++ реализацию protobuf, сбилдить protoc.exe с помощью CMake, после чего сбилдить protoc-gen-go (и не забыть добавить в переменную окружения PATH путь к protoc.exe).

Дальнейшее повествование не сильно отличается от Quick Start.

Тестовый проект на Node.js:

- server.js:
const grpc = require('grpc')
const path = require('path')
 
const root = path.join(__dirname, 'protos')
const proto = grpc.load({ root, file: 'test.proto' })
 
const server = new grpc.Server()
server.addService(proto.test.Greeter.service, {
  hello: (call, cb) => {
    console.log('req:', call.request)
    cb(null, `Hello, ${call.request.name}`)
  }
})
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure())
server.start()

- client.js:
const grpc = require('grpc')
const path = require('path')
 
const root = path.join(__dirname, 'protos')
const proto = grpc.load({ root, file: 'test.proto' })
 
const client = new proto.test.Greeter('localhost:50051', grpc.credentials.createInsecure())
client.hello({ name: 'world' }, (err, res) => {
  if (err) throw err
  console.log('res:', res)
})

Тестовый проект на Go:

- server.go:
package main
 
import (
 "context"
 "log"
 "net"
 
 pb "github.com/dab00/test-grpc/protos"
 "google.golang.org/grpc"
 "google.golang.org/grpc/reflection"
)
 
type server struct{}
 
func (s *server) Hello(ctx context.Context, req *pb.HelloReq) (*pb.HelloRes, error) {
 log.Printf("req: %v", req)
 return &pb.HelloRes{Message: "Hello " + req.Name}, nil
}
 
func main() {
 lis, err := net.Listen("tcp", ":50051")
 if err != nil {
  log.Fatalf("failed to listen: %v", err)
 }
 s := grpc.NewServer()
 pb.RegisterGreeterServer(s, &server{})
 reflection.Register(s)
 if err := s.Serve(lis); err != nil {
  log.Fatalf("failed to serve: %v", err)
 }
}
 
- client.go:
package main
 
import (
 "context"
 "log"
 
 pb "github.com/dab00/test-grpc/protos"
 "google.golang.org/grpc"
)
 
func main() {
 conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
 if err != nil {
  log.Fatalf("err: %v", err)
 }
 defer conn.Close()
 c := pb.NewGreeterClient(conn)
 
 r, err := c.Hello(context.Background(), &pb.HelloReq{Name: "world"})
 if err != nil {
  log.Fatalf("err: %v", err)
 }
 log.Printf("res: %v", r)
}
 

Билдим test.pb.go:

Комбинируем самостоятельно:
server.js + client.go:



server.go + client.js.