golang 微服务之gRPC与Protobuf的使用
RPC是什么?
所谓RPC(remoteprocedurecall远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样。
gRPC是什么?
与许多RPC系统一样,gRPC基于定义服务的思想,指定可以使用其参数和返回类型远程调用的方法。默认情况下,gRPC使用协议缓冲区作为接口定义语言(IDL)来描述服务接口和有效负载消息的结构。
gRPC有什么好处以及在什么场景下需要用gRPC
既然是server/client模型,那么我们直接用restfulapi不是也可以满足吗,为什么还需要RPC呢?下面我们就来看看RPC到底有哪些优势
gRPCvs.RestfulAPI
gRPC和restfulAPI都提供了一套通信机制,用于server/client模型通信,而且它们都使用http作为底层的传输协议(严格地说,gRPC使用的http2.0,而restfulapi则不一定)。不过gRPC还是有些特有的优势,如下:
- gRPC可以通过protobuf来定义接口,从而可以有更加严格的接口约束条件。关于protobuf可以参见笔者之前的小文GoogleProtobuf简明教程
- 另外,通过protobuf可以将数据序列化为二进制编码,这会大幅减少需要传输的数据量,从而大幅提高性能。
- gRPC可以方便地支持流式通信(理论上通过http2.0就可以使用streaming模式,但是通常web服务的restfulapi似乎很少这么用,通常的流式数据应用如视频流,一般都会使用专门的协议如HLS,RTMP等,这些就不是我们通常web服务了,而是有专门的服务器应用。)
使用场景
- 需要对接口进行严格约束的情况,比如我们提供了一个公共的服务,很多人,甚至公司外部的人也可以访问这个服务,这时对于接口我们希望有更加严格的约束,我们不希望客户端给我们传递任意的数据,尤其是考虑到安全性的因素,我们通常需要对接口进行更加严格的约束。这时gRPC就可以通过protobuf来提供严格的接口约束。
- 对于性能有更高的要求时。有时我们的服务需要传递大量的数据,而又希望不影响我们的性能,这个时候也可以考虑gRPC服务,因为通过protobuf我们可以将数据压缩编码转化为二进制格式,通常传递的数据量要小得多,而且通过http2我们可以实现异步的请求,从而大大提高了通信效率。
但是,通常我们不会去单独使用gRPC,而是将gRPC作为一个部件进行使用,这是因为在生产环境,我们面对大并发的情况下,需要使用分布式系统来去处理,而gRPC并没有提供分布式系统相关的一些必要组件。而且,真正的线上服务还需要提供包括负载均衡,限流熔断,监控报警,服务注册和发现等等必要的组件。不过,这就不属于本篇文章讨论的主题了,我们还是先继续看下如何使用gRPC。
gRPC的使用通常包括如下几个步骤
- 通过protobuf来定义接口和数据类型
- 编写gRPCserver端代码
- 编写gRPCclient端代码
protobuf的安装
mac:brewinstallprotobuf
windows:protoc下载:官方地址,然后将bin路径添加到path环境变量下去
linux:
安装需要的依赖包:
[root@localhost~]#yum-yinstallautoconfautomakelibtoolcurlmakeg++unzip [root@localhost~]#unzipprotobuf-master.zip [root@localhost~]#cdprotobuf-master
生成configure文件的脚本文件,如果不执行这步,以下操作将通不过
[root@localhostprotobuf-master]#./autogen.sh [root@localhostprotobuf-master]#./configure
可以修改安装目录通过./configure--prefix=命令,统一安装在/usr/local/protobuf下
[root@localhostprotobuf-master]#./configure--prefix=/usr/local/protobuf [root@localhostprotobuf-master]#make [root@localhostprotobuf-master]#makecheck [root@localhostprotobuf-master]#makeinstall [root@localhostprotobuf-master]#ldconfig#refreshsharedlibrarycache.
安装成功
[root@localhostprotobuf-master]#protoc-I=./--cpp_out=./test.proto
安装grpc包
goget-ugithub.com/golang/protobuf/{proto,protoc-gen-go} goget-ugoogle.golang.org/grpc protoc--go_out=plugins=grpc:.*.proto
定义接口和数据类型
syntax="proto3"; packagerpc_package; //defineaservice serviceHelloWorldService{ //definetheinterfaceanddatatype rpcSayHello(HelloRequest)returns(HelloReply){} } //definethedatatypeofrequest messageHelloRequest{ stringname=1; } //definethedatatypeofresponse messageHelloReply{ stringmessage=1; }
使用protobuf生成工具生成对应语言的库函数
protoc--go_out=plugins=grpc:.helloworld.proto
server.go
//server.go import( "log" "net" "golang.org/x/net/context" "google.golang.org/grpc" pb"helloworld/helloworld" ) const( port=":50051" ) typeserverstruct{} func(s*server)SayHello(ctxcontext.Context,in*pb.HelloRequest)(*pb.HelloReply,error){ return&pb.HelloReply{Message:"Hello"+in.Name},nil } funcmain(){ lis,err:=net.Listen("tcp",port) iferr!=nil{ log.Fatal("failedtolisten:%v",err) } s:=grpc.NewServer() pb.RegisterGreeterServer(s,&server{}) s.Serve(lis) }
client.go
packagemain //client.go import( "log" "os" "golang.org/x/net/context" "google.golang.org/grpc" pb"helloworld/helloworld" ) const( address="localhost:50051" defaultName="world" ) funcmain(){ conn,err:=grpc.Dial(address,grpc.WithInsecure()) iferr!=nil{ log.Fatal("didnotconnect:%v",err) } deferconn.Close() c:=pb.NewGreeterClient(conn) name:=defaultName iflen(os.Args)>1{ name=os.Args[1] } r,err:=c.SayHello(context.Background(),&pb.HelloRequest{Name:name}) iferr!=nil{ log.Fatal("couldnotgreet:%v",err) } log.Printf("Greeting:%s",r.Message) }
以上就是golang微服务之gRPC与Protobuf的使用的详细内容,更多关于golanggRPC与Protobuf的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。