go grpc

ddatsh

dev #go

message.proto

syntax = "proto3";

package pb;

// The greeter service definition.
service Greeter {
// Sends a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
	string name = 1;
}

// The response message containing the greetings
message HelloReply {
	string message = 1;
}

protoc编译工具

https://github.com/google/protobuf 会跳 https://github.com/protocolbuffers/protobuf

  --cpp_out=OUT_DIR           Generate C++ header and source.
  --csharp_out=OUT_DIR        Generate C# source file.
  --java_out=OUT_DIR          Generate Java source file.
  --javanano_out=OUT_DIR      Generate Java Nano source file.
  --js_out=OUT_DIR            Generate JavaScript source.
  --objc_out=OUT_DIR          Generate Objective C header and source.
  --php_out=OUT_DIR           Generate PHP source file.
  --python_out=OUT_DIR        Generate Python source file.
  --ruby_out=OUT_DIR          Generate Ruby source file.

protoc能生成那么多语言的代码,但居然本身没有产生go的代码,需要调用如protoc-gen-go这样的插件!!!


set GOPROXY=https://goproxy.io
mkdir demo
cd demo
go mod init demo

rem protoc的 --go_out 插件
go get -u github.com/golang/protobuf/protoc-gen-go 
go get -u google.golang.org/grpc

github.com/golang/protobuf/protoc-gen-go 会编译出 protoc-gen-go

要是先 google.golang.org/grpc,在其go mod也会把前者(github.com/golang/protobuf)一并给下载了,protoc-gen-go还是要自行编译下才出来

go mod 也不用 go get google.golang.org/grpc,在go build里也会自行下载

可选

//gogo
go get -u github.com/gogo/protobuf/protoc-gen-gogo
//gofast
go get -u github.com/gogo/protobuf/protoc-gen-gofast

即protoc-gen系列 3 个

go.mod

module demo

go 1.14

require (
	github.com/golang/protobuf v1.3.5
	google.golang.org/grpc v1.28.1
)

gRPC-go

grpc原是google内部项目,归属golang,放在google.golang.org下,后来对外开放迁移到github

https://github.com/grpc/grpc-go

梳理


protoc --go_out=. message.proto
protoc --go_out=plugins=grpc:. message.proto

第二个产生的则除了第一个的PB序列化和反序列化代码外,还增加服务器和客户端通讯、实现的公共库代码

github.com/gogo/protobuf

完全兼容google protobuf,主要extend了一些option

可以修饰field/enum/message/package(即对整个文件都有效)

protoc --gofast_out=plugins=grpc:. message.proto

code

server

package main

import (
	"net"
	"log"
	"google.golang.org/grpc"
	"demo/pb"
	"context"
)

// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "Hello " + in.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{})
	s.Serve(lis)
}

client

package main

import (
	"google.golang.org/grpc"
	"log"
	"demo/pb"
	"context"
)

func main() {
	conn, err := grpc.Dial("localhost:50051",grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)
	r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "dd"})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.Message)
}

gRPC HTTP协议转换

coreos的博客,转载了grpc官方博客gRPC with REST and Open APIs

etcd3改用grpc后为了兼容原来的api,同时要提供http/json方式的API

为满足这需求,要么开发两套API,要么实现一种转换机制,他们选择了后者

协议转换的网关grpc-gateway,接收客户端请求,然后决定直接转发给grpc服务还是转给http服务,当然,http服务也需要请求grpc服务获取响应,然后转为json响应给客户端