Gonet2 游戏服务器框架解析之gRPC入门(4)

Gonet2中,大量使用了gRPC,而对这个我不熟,所以这里花点时间了解一下。当然,环境我已经配好了,这里只是讲代码上如何使用,环境的搭建,网上应该蛮多。不过用gRPC要用科学的方式上网,这个对我华厦民族的同胞们,应该都不陌生了。

远程调用,一开始我想的很复杂,但是真的了解过之后,无非是,server side提供一个开方的接口,公开调用时传送数据的格式,client side遵照这种规定,调用接口提供的方法。

问题来了,既然是远程,那肯定是跨进程,甚至是跨计算机。所以可以通过网络传输的方式来远程调用。比如tcp/ip, http。

gRPC是远程调用框架的一种,传输是通过http2协议,使用接口描述语言 proto3 来定义服务接口,以及数据结构。之前有proto2的,不过proto3是最新的,语法结构有小小不同。

既然是有 A 调用 B 这个过程,有网络协议,那对于接口来说,就肯定会存在客户端,与服务端。服务端处理请求,客户端去调用接口。所以,废话了那么多,来看看一个最简单的hello world接口定义吧。

// 没得更简单了,我试着用int32来做参数和返回值,// 可是结果确是必须为message类型.// message是grpc的封装类型,相当于go语言的struct或java的class.syntax=”proto3″;message Req{}message Res{}service HelloService {rpc Hello(Req) returns (Res) {}}

生成的代码,有点吓到我的感觉!我写了6行,生成这么多!先把完整代码帖上,然后我们一点点拆开看,要是怕吓到,先跳过。

/*Package test is a generated protocol buffer package.It is generated from these files:test.protoIt has these top-level messages:ReqRes*/package testimport proto “github.com/golang/protobuf/proto”import (context “golang.org/x/net/context”grpc “google.golang.org/grpc”)// Reference imports to suppress errors if they are not otherwise used.var _ = proto.Marshaltype Req struct {}func (m *Req) Reset(){ *m = Req{} }func (m *Req) String() string { return proto.CompactTextString(m) }func (*Req) ProtoMessage() {}type Res struct {}func (m *Res) Reset(){ *m = Res{} }func (m *Res) String() string { return proto.CompactTextString(m) }func (*Res) ProtoMessage() {}// Reference imports to suppress errors if they are not otherwise used.var _ context.Contextvar _ grpc.ClientConn// Client API for HelloService servicetype HelloServiceClient interface {Hello(ctx context.Context, in *Req, opts …grpc.CallOption) (*Res, error)}type helloServiceClient struct {cc *grpc.ClientConn}func NewHelloServiceClient(cc *grpc.ClientConn) HelloServiceClient {return &helloServiceClient{cc}}func (c *helloServiceClient) Hello(ctx context.Context, in *Req, opts …grpc.CallOption) (*Res, error) {out := new(Res)err := grpc.Invoke(ctx, “/.HelloService/Hello”, in, out, c.cc, opts…)if err != nil {return nil, err}return out, nil}// Server API for HelloService servicetype HelloServiceServer interface {Hello(context.Context, *Req) (*Res, error)}func RegisterHelloServiceServer(s *grpc.Server, srv HelloServiceServer) {s.RegisterService(&_HelloService_serviceDesc, srv)}func _HelloService_Hello_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {in := new(Req)if err := codec.Unmarshal(buf, in); err != nil {return nil, err}out, err := srv.(HelloServiceServer).Hello(ctx, in)if err != nil {return nil, err}return out, nil}var _HelloService_serviceDesc = grpc.ServiceDesc{ServiceName: “.HelloService”,HandlerType: (*HelloServiceServer)(nil),Methods: []grpc.MethodDesc{{MethodName: “Hello”,Handler: _HelloService_Hello_Handler,},},Streams: []grpc.StreamDesc{},}

仔细看一下,注释写的也挺清楚了。我个人的感觉是,打个比喻来说,,同样的代码,仔细看的话,觉得难度是5,不仔细看,一下就蒙了,那难度可能是8。

上面分析过rpc调用,有服务端和客户端,还有通讯的数据格式,在这个生成分件里刚好有这三个部分。(其实,我是先看了这gRPC,再反过来分析理论的,反正说得通!)

服务端

先看一下Server部分,我加了一些注释,更详细的解释了每一部分的作用,完全是照顾新手,还有跟我一样,不喜欢仔细看代码的。

HelloServiceServer interface {Hello(context.Context, *Req) (*Res, error)}RegisterHelloServiceServer(s *grpc.Server, srv HelloServiceServer) {s.RegisterService(&_HelloService_serviceDesc, srv)}_HelloService_Hello_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) {in := new(Req)if err := codec.Unmarshal(buf, in); err != nil {return nil, err}out, err := srv.(HelloServiceServer).Hello(ctx, in)if err != nil {return nil, err}return out, nil}_HelloService_serviceDesc = grpc.ServiceDesc{ServiceName: “.HelloService”,HandlerType: (*HelloServiceServer)(nil),Methods: []grpc.MethodDesc{//服务方法数组{MethodName: “Hello”,Handler: _HelloService_Hello_Handler,},},Streams: []grpc.StreamDesc{},}你必须百分之百的把自己推销给自己。

Gonet2 游戏服务器框架解析之gRPC入门(4)

相关文章:

你感兴趣的文章:

标签云: