版权声明:本文为作者原创,如需转载请通知本人,并标明出处和作者。擅自转载的,保留追究其侵权的权利。golang群:570992072。qq 29185807 个人公众号:月牙寂道长 公众号微信号yueyajidaozhang https://cloud.tencent.com/developer/article/1454565
本文公众号文章链接:https://mp.weixin.qq.com/s/6ZNJB1Qcwdk0MaC2fWu4ng
本文csdn博客链接:https://cloud.tencent.com/developer/article/1454565
Gorilla是一个go语言的web工具箱,包含了很多的模块。本文分析的模块gorilla/rpc:implements RPC over HTTP with codec for JSON-RPC.
代码目录如下:
一、实例
来自官网http://www.gorillatoolkit.org/pkg/rpc的例子
首先New了一个Server
然后在Server中注册了Codec
接着注册了rpc service
上面是具体的rpc service
github.com/gorilla/rpc/server.go
上面有两个东西,codecs,services。后面先分析这两个部分。
二、Codec
我们从简单的入手,先看看Codec
在github.com/gorilla/rpc/server.go,对Codec接口的定义如下
有两个接口:
1、 生成CoedcRequest的接口
2、 CodecRequest接口
那么我们来看看
github.com/gorilla/rpc/json/server.go
Codec接口
按照接口来看,很简单,只是NewRequest种封装了newCodecRequest
继续看源码
通过读取http.Request中的内容,然后经过json解析结构体CodecRequest,其中封装了serverRequest结构体
接下来,我们看看这个结构体
很简单的两个结构体 serverRequest和serverResponse。就不多解释了
继续看CodeRequest的实现的接口
之前通过json解析的Method内容保存在serverRequest结构体中。
在serverRequest中的Params为json.RawMessage,所以需要继续解析params
WriteResponse则相反,将传入的数据,封装到serverResponse结构体中,然后通过json编码,然后写入到http.ResponseWriter中。
三、rpc Service
在实例中,我们看到注册了Codec之后,就注册了Service。那么Service是怎么保存的
github.com/gorilla/rpc/map.go
ServiceMap,就是一个service集合。在实例中,注册的是一个HelloService
Service中有两个部分。
1、 name、rcvr、rcvrType
name其实就是一个标识,Service的名字
rcvr、rcvrType是service的信息,在实例中就是HelloService。
2、 methods。这一部分看ServiceMethod结构体,很直白,就是一个method的信息。对应的就是HelloService类所包含的方法
类名是只有一个的,而类的方法是可以有多个的。这就是为什么分为这两个部分。
注册部分:
Setup service。其中主要是name的操作,当name为空的时候,则直接用rcvr的名字。这部分,主要是第一部分的设置
中间代码略
Setup methods。直接遍历类所包含的method,然后将其信息,放到methods这个map中。
Add to the map
将解析好的service信息,放入到serviceMap中。
整个流程很直接,清晰。
看完了注册,看看上面的get函数。先对method拆分成两个部分,一个是类名或服务名部分,一个是方法部分。然后分别进行类名或服务名的查找(图中152行)。然后根据方法名进行查找(图中158行)
至此service部分讲解完。
四、rpc server部分
直接看代码吧
github.com/gorilla/rpc/server.go
其中最主要的两部分已经讲解过了
这个是初始化
初始化Codec
这个是注册服务。这个部分也介绍过了。
现在直接进入入口
上面就是获取Codec,在实例中是json,这个具体部分已经解释过了
看源码中的英文注释,解释的很清楚。
创建code Request
然后获取Service 和method
再接着是decode args。
上面,可以忽略,不常用。
这里进入正题,调用rpc函数。这里面有一个flag poassReq,差别在于注册的rpc函数,是否要传入r *http.Request参数。
最后就是将reply通过codec编码发出去。
到这里整个流程就结束了。
龚浩华
月牙寂道长
QQ 29185807
2018年03月22日