1. 程式人生 > 實用技巧 >Go-gRPC的簡單使用

Go-gRPC的簡單使用

RPC簡介

Remote Procedure Call,縮寫為 RPC)是一個計算機通訊協議。RPC是一種伺服器-客戶端(Client/Server)模式,經典實現是一個通過傳送請求-接受迴應進行資訊互動的系統

gRPC開發步驟

  • 編寫.proto檔案,生成指定語言原始碼
  • 編寫服務端程式碼
  • 編寫客戶端程式碼

安裝

建立專案

mkdir grpc_demo
cd grpc_demo
go mod init grpc_demo

安裝gRPC

go get -u google.golang.org/grpc

安裝Protocol Buffers v3

安裝用於生成gRPC服務程式碼的協議編譯器。軟體地址

  • 解壓下載好的檔案
  • protoc二進位制檔案的路徑加到環境變數中
  • 安裝protoc的Go外掛go get -u github.com/golang/protobuf/protoc-gen-go
    • 編譯外掛protoc-gen-go將會安裝到$GOBIN,預設是$GOPATH/bin,它必須在你的$PATH中以便協議編譯器protoc能夠找到它。
C:\Users\Albin>d:

D:\>cd D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo

D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo>mkdir grpc_demo

D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo>cd grpc_demo

D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>go mod init grpc_demo
go: creating new go.mod: module grpc_demo

D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>go get -u google.golang.org/grpc
go: downloading golang.org/x/net v0.0.0-20190311183353-d8887717615a
go: extracting golang.org/x/net v0.0.0-20190311183353-d8887717615a
go: downloading golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
go: extracting golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
go: finding golang.org/x/sys latest
go: finding google.golang.org/genproto latest
go: finding golang.org/x/net latest

D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>go get -u github.com/golang/protobuf/protoc-gen-go

示例

建立專案程式碼目錄結構

mkdir helloworld\pb
mkdir helloworld\server
mkdir helloworld\client

D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>tree
資料夾 PATH 列表
卷序列號為 A021-AE06
D:.
└─helloworld
    ├─client
    ├─pb
    └─server

編寫proto程式碼

gRPC是基於Protocol Buffers。

Protocol Buffers是一種與語言無關,平臺無關的可擴充套件機制,用於序列化結構化資料。使用Protocol Buffers

可以一次定義結構化的資料,然後可以使用特殊生成的原始碼輕鬆地在各種資料流中使用各種語言編寫和讀取結構化資料。

編寫檔案

vi helloworld/pb/helloworld.proto

syntax = "proto3"; // 版本宣告,使用Protocol Buffers v3版本

package pb; // 包名


// 定義一個打招呼服務
service Greeter {
    // SayHello 方法
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 包含人名的一個請求訊息
message HelloRequest {
    string name = 1;
}

// 包含問候語的響應訊息
message HelloReply {
    string message = 1;
}
生成go語言原始碼
protoc -I helloworld/ helloworld/pb/helloworld.proto --go_out=plugins=grpc:helloworld

gRPC_demo/helloworld/pb目錄下會生成helloworld.pb.go檔案。

編寫server端go程式碼

vi grpc_demo/helloworld/server/server.go

package main

import (
	"fmt"
	"net"

	pb "grpc_demo/helloworld/pb"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "hello " + in.Name}, nil
}

func main() {
	// 監聽本地的8972埠
	lsnr, err := net.Listen("tcp", ":8972")
	if err != nil {
		fmt.Printf("failed to listen: %v", err)
		return
	}

	s := grpc.NewServer()                  // 建立gRPC伺服器
	pb.RegisterGreeterServer(s, &server{}) // 在gRPC服務端註冊服務

	reflection.Register(s) // 在給定的gRPC伺服器上註冊伺服器反射服務

	// Serve方法在lsnr上接受傳入連線,為每個連線建立一個ServerTransport和server的goroutine。
	// 該goroutine讀取gRPC請求,然後呼叫已註冊的處理程式來響應它們。
	err = s.Serve(lsnr)
	if err != nil {
		fmt.Printf("failed to serve: %v", err)
		return
	}
}

編譯並執行
cd helloworld/server
go build
./server

編寫客戶端go程式碼

package main

import (
	"context"
	"fmt"

	pb "grpc_demo/helloworld/pb"

	"google.golang.org/grpc"
)

func main() {
	// 連線伺服器
	conn, err := grpc.Dial(":8972", grpc.WithInsecure())
	if err != nil {
		fmt.Printf("faild to connect: %v", err)

	}
	defer conn.Close()

	c := pb.NewGreeterClient(conn)

	// 呼叫服務端的SayHello

	r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "biao"})

	if err != nil {
		fmt.Printf("could not greet: %v", err)
	}
	fmt.Printf("Greeting: %s !\n", r.Message)
}

執行

gRPC跨語言呼叫

使用Python語言編寫Client,然後向上面使用go語言編寫的server傳送RPC請求

安裝相關python模組
pip3 install grpcio
pip3 install grpcio-tools
pip3 install protobuf

生成python程式碼

gRPC_demo目錄執行命令

python -m grpc_tools.protoc -I helloworld/pb/ --python_out=helloworld/client/ --grpc_python_out=helloworld/client/ helloworld/pb/helloworld.proto

上面命令執行完成後,在grpc_demo/helloworld/client/目錄生成如下兩個python檔案

編寫python版client程式碼
#!/usr/bin/env python
# coding=utf-8

import logging
import grpc

import helloworld_pb2
import helloworld_pb2_grpc

def run():
    # 注意(gRPC Python Team): .close()方法在channel上是可用的。
    # 並且應該在with語句不符合程式碼需求的情況下使用。
    with grpc.insecure_channel('localhost:8972') as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='標'))
    print("Greeter client received: {}!".format(response.message))


if __name__ == '__main__':
    logging.basicConfig()
    run()
執行