不同於Restful API,gRPC 提供了更加安全也穩定的傳輸協定,
基於 Protocol Buffers ,將溝通用的模型與通道整合起來,
在 golang 裡使用 gRPC,
首先安裝相關套件
go get -u google.golang.org/grpc
撰寫協定
syntax = "proto3";
service Portal {
rpc GetPortal (PortalMessage) returns (PortalResponse) {}
}
message PortalMessage {
string target_portal = 1;
}
message PortalResponse {
string name = 1;
string kind = 2;
}
編譯協定,產生協定用的程式
protoc --go_out=plugins=grpc:. *.proto
供應端的程式
package main
import (
"context"
"errors"
"log"
"net"
pb "github.com/cyan92128505/cyangrpc/pb"
"google.golang.org/grpc"
)
type PortalService struct {
}
func (s *PortalService) GetPortal(ctx context.Context, message *pb.PortalMessage) (*pb.PortalResponse, error) {
switch message.TargetPortal {
case "AA001":
return &pb.PortalResponse{
Name: "test-server",
Kind: "test",
}, nil
case "AB001":
return &pb.PortalResponse{
Name: "online",
Kind: "normal",
}, nil
}
return nil, errors.New("Not Found Portal")
}
func main() {
listenPort, err := net.Listen("tcp", ":19003")
if err != nil {
log.Fatalln(err)
}
server := grpc.NewServer()
portalService := &PortalService{}
pb.RegisterPortalServer(server, portalService)
server.Serve(listenPort)
}
引用 Protobuf 建立出來的模組 pb,
透過 grpc.NewServer
產生伺服器,
pb 中的 RegisterPortalServer 方法是用來註冊協定服務,
其中產生的格式是 Register[主體的名稱]Server
,
並將建構出來的實體,注入進去。
需求端的程式
package main
import (
"context"
"fmt"
"log"
pb "github.com/cyan92128505/cyangrpcclient/pb"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial("127.0.0.1:19003", grpc.WithInsecure())
if err != nil {
log.Fatal("client connection error:", err)
}
defer conn.Close()
client := pb.NewPortalClient(conn)
message := &pb.PortalMessage{TargetPortal: "AA001"}
res, err := client.GetPortal(context.TODO(), message)
fmt.Printf("result:%#v \n", res)
fmt.Printf("error::%#v \n", err)
}
另一邊也是要引用所產生的模組,
透過 grpc.Dial
建立連線,
由模組內的方法 pb.NewPortalClient
,建立連線後的實體,
並透過模組內定義的方法,來取得資料。
只要定義好的協定模組,引入後便可以直接進行傳輸,
程式既文件的方式,會比以往使用 RestfulAPI 的方式,還來得方便。