golang学习5:gRPC

说明

GRPC是一个高性能、通用的开源RPC框架,基于HTTP/2协议标准和Protobuf序列化协议开发,支持众多的开发语言。

安装依赖包

go get golang.org/x/net/context
go get google.golang.org/grpc
go get google.golang.org/protobuf/reflect/protoreflect
go get google.golang.org/protobuf/runtime/protoimpl

编写IDL生成go代码

参考李文周的博客,编写了一个helloworld.proto文件,里面定义了两个服务:Greeter和GreeterCn。

syntax = "proto3"; // 版本声明,使用Protocol Buffers v3版本

option go_package = "./pb;pb";

// 定义一个英文打招呼服务
service Greeter {
    // SayHello 方法
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 包含人名的一个请求消息
message HelloRequest {
    string name = 1;
}

// 包含问候语的响应消息
message HelloReply {
    string message = 1;
}

// 定义一个中文打招呼服务
service GreeterCn {
    // SayHello 方法
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

把这个IDL转化为go源码:

$ protoc -I ./ ./helloworld.proto --go_out=plugins=grpc:./
$ ls pb/
helloworld.pb.go

编写服务端

对应helloworld.proto,编写了两个服务。

package main

import (
	"fmt"
	"net"

	pb "test_grpc/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
}

type server_cn struct{}
func (s *server_cn) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "你好 " + in.Name}, nil
}

func main() {
	// 监听本地的8972端口
	lis, 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服务端注册服务
	pb.RegisterGreeterCnServer(s, &server_cn{}) // 在gRPC服务端注册服务

	reflection.Register(s) //在给定的gRPC服务器上注册服务器反射服务
	// Serve方法在lis上接受传入连接,为每个连接创建一个ServerTransport和server的goroutine。
	// 该goroutine读取gRPC请求,然后调用已注册的处理程序来响应它们。
	err = s.Serve(lis)
	if err != nil {
		fmt.Printf("failed to serve: %v", err)
		return
	}
}

grpcurl对于其他grpc服务的感知皆来自reflection服务。这里不调用reflection.Register(s)这一行,也不影响基本的功能。

编写客户端

package main

import (
	"context"
	"fmt"
	"time"

	pb "test_grpc/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()

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	//调用英文版的接口
	c := pb.NewGreeterClient(conn)
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "yuanlulu"})
	if err != nil {
		fmt.Printf("could not greet: %v", err)
	}
	fmt.Printf("Greeting: %s !\n", r.Message)

	//调用中文版的接口
	c_cn := pb.NewGreeterCnClient(conn)
	r, err = c_cn.SayHello(ctx, &pb.HelloRequest{Name: "袁露露"})
	if err != nil {
		fmt.Printf("could not greet: %v", err)
	}
	fmt.Printf("Greeting: %s !\n", r.Message)
}

终端输出:

$ go run client.go
Greeting: Hello yuanlulu !
Greeting: 你好 袁露露 !

gRPC的四种传输方式

gRPC有四种通信方式

  • 简单rpc:这就是一般的rpc调用,一个请求对象对应一个返回对象
  • 服务端流式rpc:一个请求对象,服务端可以传回多个结果对象
  • 客户端流式rpc:客户端传入多个请求对象,服务端返回一个响应结果
  • 双向流式rpc:结合客户端流式rpc和服务端流式rpc,可以传入多个对象,返回多个响应对象

streaming rpc相比于simple rpc来说可以很好的解决一个接口发送大量数据的场景。

上面我的代码只是第一种简单rpc模式,暂时用不到,以后再摸索。

参考资料

gRPC快速入门

grpc命令行工具grpcurl使用

go-grpc-流式接口(streaming rpc

golang中使用gRPC以及四种通信方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值