Go 程序员如何使用 gRPC 的指南
Posted Go编程之旅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go 程序员如何使用 gRPC 的指南相关的知识,希望对你有一定的参考价值。
gRPC 由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。在 gRPC 里客户端应用可以像调用本地方法一样直接调用另一台不同的机器上服务端应用的方法。gRPC是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。
gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。你用 proto files 创建 gRPC 服务,用 protocol buffers 消息类型来定义方法参数和返回类型。后面例子内使用的 proto3 的新风格的 protocol buffers,它拥有轻量简化的语法、一些有用的新功能,并且支持更多新语言。
通过本教程学习,你将学会:
● 在一个 .proto 文件内定义服务。
● 用 protocol buffer 编译器生成服务器和客户端代码。
● 使用 gRPC 的 Go API 为你的服务实现一个简单的客户端和服务器。
有了 gRPC, 我们可以一次性的在一个 .proto 文件中定义服务并使用任何支持它的语言去实现客户端和服务器,反过来,它们可以在各种环境中,从Google的服务器到你自己的平板电脑—— gRPC 帮你解决了不同语言及环境间通信的复杂性.使用 protocol buffers 还能获得其他好处,包括高效的序列号,简单的 IDL 以及容易进行接口更新。
下面就开始一步一步的来学习吧
定义服务
使用 protocol buffers去定义 gRPC service 和方法 request 以及 response 的类型。gRPC 允许你定义4种类型的 service 方法,包括:简单 RPC 、服务器端流式 RPC、客户端流式 RPC 、双向流式 RPC ;本文只介绍最简单的也是最常用的简单RPC方法
fetch_service.proto
syntax = "proto3";
package grpcservice;
//定义 service
service FetchService {
rpc Fetch(FetchRequest) returns (FetchResponse) {}
}
//定义方法入参 request
message FetchRequest {
string name = 1;
repeated int64 ids = 2;
}
//定义方法返回参数 response
message FetchResponse {
repeated string results = 1;
}
安装 protocol buffer 编译器
go get -u github.com/golang/protobuf/protoc-gen-go
生成客户端和服务器端代码
在proto文件所在目录下执行下面命令
protoc --go_out=plugins=grpc:. fetch_service.proto
会在当前目录下生成文件fetch_service.pb.go
创建服务器
实现我们服务定义的生成的服务接口:
做我们的服务的实际的“工作”。
运行一个 gRPC 服务器,监听来自客户端的请求并返回服务的响应。
package main
import (
"context"
"net"
"google.golang.org/grpc"
pb "github.com/KenmyZhang/golang-lib/grpc-service/proto"
log "github.com/KenmyZhang/golang-lib/zaplogger"
"google.golang.org/grpc/reflection"
"strconv"
"fmt"
)
const (
port = ":50051"
)
type server struct{}
func (s *server) Fetch(ctx context.Context, in *pb.FetchRequest) (*pb.FetchResponse, error) {
log.Info(fmt.Sprintf("FetchRequest:%+v", in))
ids := ""
for _, val := range in.Ids {
ids = ids + strconv.FormatInt(val, 10)
}
rst := &pb.FetchResponse{Results: []string{"name:" + in.Name, "ids:" + ids}}
log.Info(fmt.Sprintf("FetchResponse:%+v", rst))
return rst, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Error(fmt.Sprintf("failed to listen: %v", err))
return
}
s := grpc.NewServer()
pb.RegisterFetchServiceServer(s, &server{})
// Register reflection service on gRPC server.
log.Info(fmt.Sprintf("listen:%v", port))
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Error(fmt.Sprintf("failed to serve: %v", err))
return
}
}
调用服务方法
package main
import (
"context"
"log"
"os"
"time"
"google.golang.org/grpc"
pb "github.com/KenmyZhang/golang-lib/grpc-service/proto"
)
const (
address = "localhost:50051"
defaultName = "world"
)
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.NewFetchServiceClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.Fetch(ctx, &pb.FetchRequest{Name: name, Ids: []int64{234,456}})
if err != nil {
log.Fatalf("could not fetch: %v", err)
}
log.Printf("Greeting: %+v", r.Results)
}
以上是关于Go 程序员如何使用 gRPC 的指南的主要内容,如果未能解决你的问题,请参考以下文章
[教程,Part 2]如何使用HTTP/REST端点,中间件,Kubernetes等开发Go gRPC微服务
[go微服务-17] gRPC和 Apache Thrift 之间 如何进行选型?