首页>新闻>深圳区块链培训班费用多少

深圳区块链培训班费用多少

来源:深圳兄弟连教育

时间:2019/7/26 15:33:50

gRPC简介

gRPC是Google公司基于Protobuf开发的跨语言的开源RPC框架。gRPC基于HTTP/2协议设计,可以基于一个HTTP/2链接提供多个服务,对于移动设备更加友好。本节将讲述gRPC的简单用法。

gRPC框架技术栈

Go语言的gRPC技术栈如图4-1所示:


说明:

1、底层为TCP或Unix Socket协议。

2、第二层是HTTP/2协议的实现。

3、针对Go语言的gRPC核心库。

4、应用程序通过gRPC插件生产的Stub代码和gRPC核心库通信,也可以直接和gRPC核心库通信。

gRPC的安装

命令安装通过如下命令可以安装go版本的gRPC框架:

go get -u google.golang.org/grpc

通过go的get命令可以安装完成。

下载安装如果安装失败,也可以自行到github网站下载grpc-go代码库,然后解压,放入到当前系统的$GOPATH/src中,创建google.golang.org目录,将解压后的文件放入到新创建的目录中,修改解压后的目录名称为grpc,

gRPC使用方法

1、准备.proto文件

创建person.proto文件,定义HelloService接口:

syntax = "proto3";package person;message Person {    string name = 1;  

int32 age = 2;}service HelloService{    rpc Hello (Person) returns

(Person);}

2、使用gRPC插件生成gRPC代码:

$ protoc --go_out=plugins=grpc:. person.proto

gRPC插件会为服务端和客户端生成不同的接口:

type HelloServiceServer interface { Hello(context.Context, *Person)

(*Person, error)}type HelloServiceClient interface { Hello(ctx context.Context,

in *Person, opts ...grpc.CallOption) (*Person, error)}

gRPC通过context.Context参数,为每个方法调用提供了上下文支持。客户端在调用方法的时候,可以通过可选的grpc.CallOption类型的参数提供额外的上下文信息。

3、基于HelloServiceServe接口实现具体服务

基于服务端的HelloServiceServer接口可以重新实现HelloService服务:

type HelloService struct {}func (hello *HelloService) Hello(ctx

context.Context, args *person.Person) (*person.Person, error) { reply :=

&person.Person{Name: "hello:" + args.GetName()} return reply, nil}

4、gRPC服务启动流程

在服务端的main中,执行启动服务和监听程序,如下所示:

func main() { grpcServer := grpc.NewServer()  

person.RegisterHelloServiceServer(grpcServer, new(HelloService)) lis, err :=

net.Listen("tcp", ":1234") if err != nil { log.Fatal(err) }

grpcServer.Serve(lis)}

首先是通过grpc.NewServer()构造一个gRPC服务对象,然后通过gRPC插件生成的RegisterHelloServiceServer函数注册我们实现的HelloServiceImpl服务。然后通过grpcServer.Serve(lis)在一个监听端口上提供gRPC服务。

5、客户端链接gRPC服务

在客户端中使用grpc连接rpc服务的实现也很简单:

func main() { //1、Dail连接 conn, err := grpc.Dial("localhost:1234",

grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer conn.Close() client

:= person.NewHelloServiceClient(conn) per := &person.Person{Name: "Davie",

Age: 18} response, err := client.Hello(context.Background(), per) if err != nil

{ log.Fatal(err) } fmt.Println(response.GetName(), response.GetAge())}

其中grpc.Dial负责和gRPC服务建立链接,然后NewHelloServiceClient函数基于已经建立的链接构造HelloServiceClient对象。返回的client其实是一个HelloServiceClient接口对象,通过接口定义的方法就可以调用服务端对应的gRPC服务提供的方法。

gRPC和标准的RPC的区别

gRPC和标准库的RPC框架有一个区别,gRPC生成的接口并不支持异步调用。不过我们可以在多个Goroutine之间安全地共享gRPC底层的HTTP/2链接,因此可以通过在另一个Goroutine阻塞调用的方式模拟异步调用。

gRPC流

RPC是远程函数调用,因此每次调用的函数参数和返回值不能太大,否则将严重影响每次调用的响应时间。因此传统的RPC方法调用对于上传和下载较大数据量场景并不适合。同时传统RPC模式也不适用于对时间不确定的订阅和发布模式。为此,gRPC框架针对服务器端和客户端分别提供了流特性。

服务端或客户端的单向流是双向流的特例,我们在HelloService增加一个支持双向流的Channel方法:

rpc Channel (stream Person) returns (stream Person);

关键字stream指定启用流特性,参数部分是接收客户端参数的流,返回值是返回给客户端的流。

1、 重新编译person.proto文件

通过如下命令重新编译:

protoc --go_out=plugins=grpc:. person.proto

重新生成代码可以看到接口中新增加的Channel方法的定义:

type HelloServiceServer interface { Hello(context.Context, *Person)

(*Person, error) Channel(HelloService_ChannelServer) error}type

HelloServiceClient interface { Hello(ctx context.Context, in *Person, opts

...grpc.CallOption) (*Person, error) Channel(ctx context.Context, opts

...grpc.CallOption) (HelloService_ChannelClient, error)}

2、生成新的方法参数

在服务端的Channel方法参数是一个新的HelloService_ChannelServer类型的参数,可以用于和客户端双向通信。客户端的Channel方法返回一个HelloService_ChannelClient类型的返回值,可以用于和服务端进行双向通信。

HelloService_ChannelServer和HelloService_ChannelClient均为接口类型:

type HelloService_ChannelServer interface { Send(*Person) error Recv()

(*Person, error) grpc.ServerStream}type HelloService_ChannelClient interface {

Send(*Person) error Recv() (*Person, error) grpc.ClientStream}

3、服务端实现流接口方法实现

通过以上代码,我们可以发现服务端和客户端的流辅助接口均定义了Send和Recv方法用于流数据的双向通信。

func (hello *HelloService) Channel(stream

person.HelloService_ChannelServer) error { for { args, err := stream.Recv() if

err != nil { if err == io.EOF { return nil } return err } response :=

&person.Person{Name: "姓名:" + args.GetName(), Age: args.GetAge()} err =

stream.Send(response) if err != nil { return nil } }}

服务端在循环中接收客户端发来的数据,如果遇到io.EOF表示客户端流被关闭,如果函数退出表示服务端流关闭。生成返回的数据通过流发送给客户端,双向流数据的发送和接收都是完全独立的行为。需要注意的是,发送和接收的操作并不需要一一对应,用户可以根据真实场景进行组织代码。

4、客户端实现流方法的调用

客户端需要先调用Channel方法获取返回的流对象:

stream, err := client.Channel(context.Background()) if err != nil {

log.Fatal(err) }

将发送和接收操作放到两个独立的Goroutine。向服务端发送数据和接受数据代码实现如下:

//向服务端发送数据 go func() { for { if err := stream.Send(&person.Person{Name:

"Davie", Age: 18}); err != nil { log.Fatal(err) } time.Sleep(time.Second) } }()

//循环中接收服务端返回的数据 for { response, err := stream.Recv() if err != nil { if err ==

io.EOF { break } log.Fatal(err) } fmt.Println(response.GetName())

通过该案例和代码,我们演示了gRPC框架的使用流程,以及gRPC框架流的使用。

  • 上一篇:深圳区块链培训哪家比较专业费用多少
  • 下一篇:深圳有推荐区块链培训学校么
  • 相关推荐 更多>

    深圳哪有靠谱java培训学校

    深圳有哪些java培训班

    深圳专业java培训班多少钱

    深圳有名的java培训机构学费多...

    深圳学习java培训学校要多少钱

    深圳java培训机构学费大概多少...

    预约体验课

    版权所有:搜学搜课(www.soxsok.com)

  • 在线咨询
  • 电话咨询
  • 预约试听

  • ;