table of Contents
Outline
GRPC the beginning, learning to use this article gRPC, output a Hello World.
- Implement server gRPC with Go.
- Go with the realization gRPC clients.
gRPC supports four types of service method, and this time we will realize individual RPC server-side streaming RPC.
Four categories of service method
Individual RPC
The server sends a request to the server, gets a response from the server, just like a normal function call.
rpc SayHello(HelloRequest) returns (HelloResponse){}
RPC server streaming
The client sends a request to the server, can obtain a series of data flow to read the message. The client has been read from the returned data stream until no more news so far.
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
Streaming client RPC
A client data stream is written and provided with a series of messages sent to the server. Once the client has completed message is written, it will wait for the server to read the message and returns a response.
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}
Two-way flow RPC
Both sides can be transmitted separately flow through a series of messages read and write data. The two data streams is independent of the operation, so the client and server can read and write its desired any order, for example: the server may wait for all of the clients before the write reply message, or it may first read a message write a message, or other combination of reading and writing. Message in order for each data stream will be maintained.
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){}
installation
Installation protobuf compiler
brew install protobuf
verification:
protoc --version
//输出:libprotoc 3.7.1
Go protobuf plug-in installation
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
Installation grpc-go
go get -u google.golang.org/grpc
Write a Hello World Service
- Write server
.proto
file - Generate server
.pb.go
files and synchronize to the client - Write server provides the interface code
- The interface code to write client calls
Directory Structure
├─ hello -- 代码根目录
│ ├─ go_client
│ ├── main.go
│ ├── proto
│ ├── hello
│ ├── hello.pb.go
│ ├─ go_server
│ ├── main.go
│ ├── controller
│ ├── hello_controller
│ ├── hello_server.go
│ ├── proto
│ ├── hello
│ ├── hello.pb.go
│ ├── hello.proto
This creates a directory for go_client and post go_server can be split into two projects.
Write file server hello.proto
syntax = "proto3"; // 指定 proto 版本
package hello; // 指定包名
// 定义 Hello 服务
service Hello {
// 定义 SayHello 方法
rpc SayHello(HelloRequest) returns (HelloResponse) {}
// 定义 LotsOfReplies 方法
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
}
// HelloRequest 请求结构
message HelloRequest {
string name = 1;
}
// HelloResponse 响应结构
message HelloResponse {
string message = 1;
}
For more Protobuf syntax, see:
https://developers.google.com/protocol-buffers/
Generation server .pb.go
protoc -I . --go_out=plugins=grpc:. ./hello.proto
While the generated hello.pb.go
copy to a client.
View more command parameters, perform protoc, see OPTION.
Write server provides the interface code
// hello_server.go
package hello_controller
import (
"fmt"
"golang.org/x/net/context"
"hello/go_server/proto/hello"
)
type HelloController struct{}
func (h *HelloController) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloResponse, error) {
return &hello.HelloResponse{Message : fmt.Sprintf("%s", in.Name)}, nil
}
func (h *HelloController) LotsOfReplies(in *hello.HelloRequest, stream hello.Hello_LotsOfRepliesServer) error {
for i := 0; i < 10; i++ {
stream.Send(&hello.HelloResponse{Message : fmt.Sprintf("%s %s %d", in.Name, "Reply", i)})
}
return nil
}
// main.go
package main
import (
"log"
"net"
"hello/go_server/proto/hello"
"hello/go_server/controller/hello_controller"
"google.golang.org/grpc"
)
const (
Address = "0.0.0.0:9090"
)
func main() {
listen, err := net.Listen("tcp", Address)
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
s := grpc.NewServer()
// 服务注册
hello.RegisterHelloServer(s, &hello_controller.HelloController{})
log.Println("Listen on " + Address)
if err := s.Serve(listen); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}
run:
go run main.go
2019/07/28 17:51:20 Listen on 0.0.0.0:9090
Write the client requests the interface code
package main
import (
"hello/go_client/proto/hello"
"io"
"log"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
// gRPC 服务地址
Address = "0.0.0.0:9090"
)
func main() {
conn, err := grpc.Dial(Address, grpc.WithInsecure())
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
// 初始化客户端
c := hello.NewHelloClient(conn)
// 调用 SayHello 方法
res, err := c.SayHello(context.Background(), &hello.HelloRequest{Name: "Hello World"})
if err != nil {
log.Fatalln(err)
}
log.Println(res.Message)
// 调用 LotsOfReplies 方法
stream, err := c.LotsOfReplies(context.Background(),&hello.HelloRequest{Name: "Hello World"})
if err != nil {
log.Fatalln(err)
}
for {
res, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Printf("stream.Recv: %v", err)
}
log.Printf("%s", res.Message)
}
}
run:
go run main.go
2019/07/28 17:58:13 Hello World
2019/07/28 17:58:13 Hello World Reply 0
2019/07/28 17:58:13 Hello World Reply 1
2019/07/28 17:58:13 Hello World Reply 2
2019/07/28 17:58:13 Hello World Reply 3
2019/07/28 17:58:13 Hello World Reply 4
2019/07/28 17:58:13 Hello World Reply 5
2019/07/28 17:58:13 Hello World Reply 6
2019/07/28 17:58:13 Hello World Reply 7
2019/07/28 17:58:13 Hello World Reply 8
2019/07/28 17:58:13 Hello World Reply 9
View Source: https://github.com/xinliangnote/Go
Recommended Reading
Gin framework
- Gin framework - Custom Error Handling
- Gin frame - binding and validation data
- Gin frame - logging using Logrus
- Gin frame - routing configuration and installation
Basics
- Go - Function
- Go - cycling
- Go - Map collection
- Go - Struct structure
- Go - Slice Slice
- Go - Array
- Go - variable declaration
- Go - Environment Installation
This article Welcome forwarding, please indicate the source and author, thank you!