gRPC是什么
gRPC是一个高性能、开源、通用的 RPC框架 。基于HTTP/2协议标准设计开发,默认采用Protocol Buffers数据序列化协议(Protocol Buffers基本语法),支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务,并且为客户端和服务端自动生成可靠的功能库
gRPC应用场景
在gRPC客户端可以直接调用不通服务器上的远程程序,就想调用本地程序一样,很容易构建分布式应用和服务。和很多RPC系统一样,服务负责实现定义好的接口并处理客户端请求,客户端根据接口描述直接调用需要的服务。客户端和服务器可以分别使用gRPC支持的不同语言实现
官方配置教程链接
gPRC列子 hello gRPC
编写流程
- 编写.proto描述文件
- 编译生成.pb.go文件
- 客户端实现约定的接口并提供服务
- 客户端按照约定调用方法请求服务
代码示例
helloworld.proto rpc服务描述文件
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
// 问候服务定义。
service Greeter {
// 发送问候
rpc SayHello (HelloRequest) returns (HelloReply) {}
// 再次发送问候
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
// 包含用户名的请求消息
message HelloRequest {
string name = 1;
}
// 包含问候语的响应消息
message HelloReply {
string message = 1;
}
文件中定义了一个Greeter Service 该服务包含了一个SayHello方法和SayHelloAgain方法 同时声明了HelloRequest和HelloReply消息结构用于请求和响应。客户端使用HelloRequest参数调用SayHello方法请求服务端 服务端响应HelloReply消息
使用命令protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
生成Golang源文件 helloworld..pb.go,源文件中包含消息传递的请求和响应结构。服务端注册对象的方法 创建客户端 以及调用服务端方法
服务器端代码
//go:生成 protoc -I ../helloworld --go_out=plugins=grpc:../helloworld ../helloworld/helloworld.proto
// Package main implements a server for Greeter service.
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
port = ":50051"
)
// 服务器用于实现helloworld.greeter服务器。
type server struct{}
// say hello实现helloworld.greeter服务器
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
客户端代码
// Package main implements a client for Greeter service.
package main
import (
"context"
"log"
"os"
"time"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// 建立到服务器的连接
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// 连接服务器并打印出其响应
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}
然后分别运行服务器端和客户端
可以看到程序已经ok!