加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

【GOLANG】第一章 RPC 源码分析

发布时间:2020-12-16 18:25:57 所属栏目:大数据 来源:网络整理
导读:第一章 RPCgolang 源码分析 rpc服务器也就是在tcp服务器的基础上加上自定义的rpc协议而已。一个rpc协议里,主要有个3个非常重要的信息。 · 调用的远程method名字,一般就是一个函数名 call参数,也就是发送给 服务器 的数据 客户端生成的调用请求seq 1.1 官

第一章 RPCgolang源码分析

rpc服务器也就是在tcp服务器的基础上加上自定义的rpc协议而已。一个rpc协议里,主要有个3个非常重要的信息。

·调用的远程method名字,一般就是一个函数名

call参数,也就是发送给服务器的数据

客户端生成的调用请求seq

1.1官方例子

首先看看官方给出的使用例子:看看rpc.Register到底做了什么事情!

typeArgsstruct{
A,Bint}

func(t*Arith)Multiply(args*Args,reply*int)error{*reply=args.A*args.Breturnnil

arith:=new(Arith)rpc.Register(arith)

找到regsiter主要函数如下所示:主要是把结构体加入到Server结构体中serverMap中,初始化工作,赋值方法等操作。

func(server*Server)register(rcvrinterface{},namestringuseNameboolerror{s:=new(service)。。。。。。。。。。。。。。。。server.serviceMap[s.name]=sreturnnil}

那么rpc服务器如何能够根据method去调用对应的方法呢?Go语言在这里其实采用反射的手段,虽然表面上是注册的对象,实际却是通过反射取得了对象的所有方法,然后采用了map表保存了method到方法的映射

1.2结构体

typeServerstructmusync.RWMutex//protectstheserviceMapserviceMapmap[]*servicereqLocksync.Mutex//protectsfreeReqfreeReq*RequestrespLocksync.Mutex//protectsfreeRespfreeResp*Response}

rpc的service包括方法名、方法反射,类型等

servicenamestring//nameofservicercvrreflect.Value//receiverofmethodsfortheservicetypreflect.Type//typeofthereceivermethod[]*methodType//registeredmethods}

//AServerCodecimplementsreadingofRPCrequestsandwritingof//RPCresponsesfortheserversideofanRPCsession.//TheservercallsReadRequestHeaderandReadRequestBodyinpairs//toreadrequestsfromtheconnection,anditcallsWriteResponseto//writearesponseback.TheservercallsClosewhenfinishedwiththe//connection.ReadRequestBodymaybecalledwithanil//argumenttoforcethebodyoftherequesttobereadanddiscarded.
ServerCodecReadRequestHeader(*Request)ReadRequestBody({})//WriteResponsemustbesafeforconcurrentusebymultiplegoroutines.WriteResponse(*ResponseClose()}

ReadRequestHeaderReadRequestBody一起使用从connectionnil读取body取出并丢弃.最终使用的都是这几个函数,读取和发送response

只需要实现ServerCodec这个接口,就可以自定义服务端的编码解码器,实现自定义的rpc协议了。Gorpc服务器端和客户端都是默认使用的Gob序列化协议数据。

1.3Server端处理请求

Accept(lisnet.Listener){forconnerr:=lis.iferr!=log.Print("rpc.Serve:accept:"err.Error())return}goserver.ServeConn(conn)Accept用来处理一个监听器,一直在监听客户端的连接,一旦监听器接收了一个连接,则还是交给ServeConn在另外一个goroutine中去处理:

//ServeConnrunstheserveronasingleconnection.//ServeConnblocks,servingtheconnectionuntiltheclienthangsup.//ThecallertypicallyinvokesServeConninagostatement.//ServeConnusesthegobwireformat(seepackagegob)onthe//connection.Touseanalternatecodec,useServeCodec.(connio.ReadWriteCloser){buf:=bufio.NewWritersrv:=&gobServerCodec{rwc:conndec:gob.NewDecoderenc:gob.NewEncoder(buf)encBuf:bufServeCodec(srv)}

//根据指定的codec进行协议解析

//ServeCodecislikeServeConnbutusesthespecifiedcodecto//decoderequestsandencoderesponses.(codecServerCodec){sending:=(sync.Mutex)servicemtypereqargvreplyvkeepReadingerr:=server.readRequest(codec)debugLog&&err!=io.EOF{Println"rpc:"err)!keepReading{break//sendaresponseifweactuallymanagedtoreadaheader.req!=sendResponse(sendinginvalidRequestcodecfreeRequest(req)continueservice.call(serversendingcodec)codec.解码request和编码response

funcreadRequestHeader(codecServerCodec)

读取头部信息,获取service和方法。

(s*(server*Serversending*sync.Mutexmtype*methodTypereq*Requestreplyvreflect.ValuecodecServerCodec){mtype.Lockmtype.numCalls++Unlockfunction:=mtype.method.Func//Invokethemethod,providinganewvalueforthereply.returnValues:=function.Call([]reflect.Value{s.rcvrreplyv})//Thereturnvalueforthemethodisanerror.errInter:=returnValues0].Interfaceerrmsg:=""errInter!=errmsg=errInter.().replyv.errmsg)

returnValuesCall([]reflect.Value{s.rcvrargvreplyv})

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读