A simple API using protobuf and gRPC
Bài đăng này đã không được cập nhật trong 3 năm
This tutorial provides a basic Go programmer’s introduction to working with gRPC.
Goal of this tutorial
- Define a service in a .proto file.
- Generate server and client code using the protocol buffer compiler.
- Use the Go gRPC API to write a simple client and server for your service.
1. Perquisites
This requires Go 1.6 or later, ProtocolBuffers 3.0.0 or later
// Ubuntu 16.04
$sudo apt install libprotobuf-dev
Requires that GOPATH is set
$ go help gopath
$ # ensure the PATH contains $GOPATH/bin
$ export PATH=$PATH:$GOPATH/bin
for fish guy!!!
set -gx PATH $PATH $GOPATH/bin
Then, go get -u as usual.
go get google.golang.org/grpc
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
2. Guidelines
Make sure that your $GOPATH/bin is in your $PATH.
a. Define your service in gRPC
pb/service.proto:
syntax = "proto3";
option go_package = "echo";
// Echo Service
//
// Echo Service API consists of a single service which returns a message.
package echo;
import "google/api/annotations.proto";
// Message represents a simple message sent to the Echo service.
message Message {
// Id represents the message identifier.
string id = 1;
// The message to be sent.
string msg = 2;
}
// Echo service responds to incoming echo requests.
service EchoService {
// Echo method receives a simple message and returns it.
// The message posted as the id parameter will also be returned.
rpc Echo(Message) returns (Message) {
option (google.api.http) = {
post: "/v1/example/echo/{id}/{msg}"
};
}
}
b. Gnerate gRPC stub
Generating client and server code
$ protoc -I/usr/local/include -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=Mgoogle/api/annotations.proto=github.com/gengo/grpc-gateway/third_party/googleapis/google/api,plugins=grpc:. \
pb/service.proto
Generate reverse-proxy for your RESTful API
$ protoc -I/usr/local/include -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--grpc-gateway_out=logtostderr=true:. \
pb/service.proto
c. Write your Server code
server/server.go:
package main
import (
"flag"
"github.com/golang/glog"
pb "github.com/go-grpc-tutorial/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"
"net"
)
// Implements of EchoServiceServer
type echoServer struct{}
func newEchoServer() pb.EchoServiceServer {
return new(echoServer)
}
func (s *echoServer) Echo(ctx context.Context, msg *pb.Message) (*pb.Message, error) {
glog.Info(msg)
return msg, nil
}
func Run() error {
listen, err := net.Listen("tcp", ":50051")
if err != nil {
return err
}
server := grpc.NewServer()
pb.RegisterEchoServiceServer(server, newEchoServer())
server.Serve(listen)
return nil
}
func main() {
flag.Parse()
defer glog.Flush()
if err := Run(); err != nil {
glog.Fatal(err)
}
}
server/server-rproxy.go: (REST JSON API)
package main
import (
"flag"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/golang/glog"
pb "github.com/go-grpc-tutorial/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
var (
echoEndpoint = flag.String("echo_endpoint", "localhost:50051", "endpoint of EchoService")
)
func RunEndPoint(address string, opts ...runtime.ServeMuxOption) error {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
mux := runtime.NewServeMux(opts...)
dialOpts := []grpc.DialOption{grpc.WithInsecure()}
err := pb.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint, dialOpts)
if err != nil {
return err
}
http.ListenAndServe(address, mux)
return nil
}
func main() {
flag.Parse()
defer glog.Flush()
if err := RunEndPoint(":8080"); err != nil {
glog.Fatal(err)
}
}
d. Client Side
server/client.go:
package main
import (
"log"
"os"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "github.com/go-grpc-tutorial/pb"
)
const (
address = "localhost:50051"
defaultName = "PhuongDV"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewEchoServiceClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.Echo(context.Background(), &pb.Message{Id: "1", Msg: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Msg)
}
e. Try it out!
To compile and run the server, assuming you are in the folder $GOPATH/src/github.com/go-grpc-tutorial, simply:
$ go run server/server.go
Likewise, to run the client:
$ go run client/client.go
017/03/06 17:36:33 Greeting: PhuongDV
Call REST API
$ curl -X POST "http://localhost:8080/v1/example/echo/1/PhuongDV"
{"id":"1","msg":"PhuongD"}
Copy by @ https://pdoviet.wordpress.com/2017/03/06/a-simple-api-using-protobuf-and-grpc/
All rights reserved