前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >leaf源码分析(一)----chanrpc

leaf源码分析(一)----chanrpc

作者头像
月牙寂道长
发布2019-07-02 13:14:12
1.1K0
发布2019-07-02 13:14:12
举报
文章被收录于专栏:月牙寂

版权声明:本文为作者原创,如需转载请通知本人,并标明出处和作者。擅自转载的,保留追究其侵权的权利。golang群:570992072。qq 29185807 个人公众号:月牙寂道长 公众号微信号yueyajidaozhang https://cloud.tencent.com/developer/article/1454498

本文公众号链接为:https://mp.weixin.qq.com/s/bzh3jZJkz96WxbPX4zF75A

Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器。

阅读中文文档,其中介绍的是

leaf/chanrpc 提供了一套基于 channel 的 RPC 机制,用于游戏服务器模块间通讯。chanrpc提供了三种模式

  1. 同步模式,调用并等待 ChanRPC 返回
  2. 异步模式,调用并提供回调函数,回调函数会在 ChanRPC 返回后被调用
  3. Go 模式,调用并立即返回,忽略任何返回值和错误

那么下面看源码

源码目录为:

先看看github.com/name5566/leaf/chanrpc/example_test.go,里面演示了chanrpc的具体用法

chanrpc分为server和client两个部分

以上代码中是server的一个过程

1、初始化了一个server。

2、接着,注册了server提供的rpc函数。rpc支持三种类型

代码语言:javascript
复制
func([]interface{})                           参数为[]interface,无返回值
func([]interface{}) interface{}           参数为[]interface,返回值为interface
func([]interface{}) []interface{}         参数为[]interface,返回值为[]interface

3、最后server开启Exec执行rpc函数

以上为client过程

1、创建了client

2、同步调用。提供了集中调用方法。可以根据返回值分类来记忆:

Call0,Call1,CallN

3、异步调用。异步与同步的区别在于,异步执行调用完就会直接返回,但其注册了cb(call back)回调函数。在最后会等待异步执行完毕后,执行cb

4、Go模式。和异步调用的区别就是无cb。也是立即返回的。

用法分析完后,看具体的源码

github.com/name5566/leaf/chanrpc/chanrpc.go

基本数据结构RetInfo

代码语言:javascript
复制
ret interface{}      记录返回值,有三种类型

err error              记录err
cb interface{}      保存上下文中的Call back函数

基本数据结构CallInfo

代码语言:javascript
复制
f       interface{}                rpc调用的函数
args    []interface{}           参数
chanRet chan *RetInfo       传递ret的chan
cb      interface{}              保存上下文中的Call back函数

Server

Server数据结构

代码语言:javascript
复制
functions map[interface{}]interface{}           用于保存注册rpc函数
ChanCall  chan *CallInfo                            用于接收rpc调用chan

以上是Server初始化。注意其中l,是chancall的容量,意味着,异步调用时候能够异步传递多少函数。

Register

以上是注册接口(注意:此处并非线程安全的)

1、通过switch来对类型做一个判断。default中,则是不支持的类型,将会panic

2、判断是否重复注册

3、注册,其实就是放到map中。

Exec

回顾下用法

在github.com/name5566/leaf/chanrpc/example_test.go中

从以上代码中可以看出,就是从ChanCall中,取出CallInfo信息,然后执行。

继续跟踪

根据不同的rpc函数类型,封装不同的RetInfo。继续跟踪

1、当client调用的时候,没有注册chanret时,也就是为nil,不需要传递返回值,则直接返回不处理。否则继续往下处理

2、将client调用rpc时候,注册的cb,传递到RetInfo中。并将RetInfo发送到CallInfo中的chanRet中,将ret信息和cb传递给client。

到此Server所处理的流程都已经完了

Client

代码语言:javascript
复制
s               *Server                            对应的Server
chanSyncRet     chan *RetInfo             同步调用时候,用于接收ret的chan
ChanAsynRet     chan *RetInfo            异步调用的时候,用于接收ret和cb的chan
pendingAsynCall int                           异步调用的计数器

初始化

两种模式

1、先初始化client结构体。这里要注意的是

同步chanSyncRet容量为1

异步cahnAsynRet的容量是初始化为参数l的。

2、将其Attach,附属到server中。其实就是将s初始化到client中的成员变量s

这种模式需要调用两次函数

这种模式,是将初始化和Attach封装到了一起。

同步调用

步骤是一样的

1、查找函数f

2、远程调用call。其中chanRet赋值的是chanSyncRet,block设置为true。这个是区别于异步调用模式的。

3、从chanSyncRet中接收ret,并将ret返回给上一层

f函数,功能就是一个,从server的注册函数中,查找到对应id的函数,将其返回。

其中做了一些函数的检查。

call函数:将CallInfo信息通过server的chancall发送给server。

1、同步模式,会阻塞等待

2、异步模式,会直接发送。如果chancall的容量不够,则会直接执行default。

在NewServer的时候,有个参数l,就是用来设置chancall的容量的。

异步调用

上述步骤

1、参数分割,最后一个参数是cb

2、对cb函数,类型检查,不支持的函数的话,则panic

3、判断异步调用是不是超出了异步chanAsynRet的容量,如果是,则直接将err返回

4、调用asynCall,并计数pendingAsynCall

以上步骤

1、从f中查找对应id的rpc函数。如果未查到,则直接通过chanAsynRet将err返回

2、call,这里面chanRet赋值的是chanAsynRet。blcok设置为false。这是区别于同步调用的。

异步执行结果

通过RetInfo中获取到cb函数,通过不同类型,进行cb调用。三种类型如下

代码语言:javascript
复制
   ri.cb.(func(error))(ri.err)

   ri.cb.(func(interface{}, error))(ri.ret, ri.err)

   ri.cb.(func([]interface{}, error))(assert(ri.ret), ri.err)

Go模式

其实这个模式是最简单的

1、查找对应id的rpc函数

2、构建CallInfo发送到chancall中

不需要构建返回,也没有cb

close

还有一个没讲解的那就是close

server close

1、会先将chancall关闭掉

2、处理chancall中剩余的rpc调用。并不会执行,而是执行返回错误

client close

同步的是不用处理的,肯定会处理结束

主要的是异步的,异步有个计数器,会一直处理等待计数器为0

龚浩华

月牙寂道长

QQ 29185807

2018年04月17日

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年04月17日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档