开发者学堂课程【阿里巴巴分布式服务框架 Dubbo 快速入门:服务调用流程】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/624/detail/9481
服务调用流程
内容介绍:
一、代理对象如何进行方法调用
二、总结
一、代理对象如何进行方法调用
以 Debug 实际运行为准进行演示。
进入调用方法,看到 user service 确实是一个代理对象,这个代理对象是层层封装了各种 Invoker,Invoker 里是真正要执行的一些功能方法。
Stepinto 进来以后,拿到要执行的方法信息,包括参数的类型信息等等。
接着有一个叫 invoker.invoke,然而这个 Invoker 里本身就是层层封装的结果,放行,再带 stepinto,在 into之前,会看到它需要 Invoker 执行,会把方法以及参数封装成一个叫 RPC 执行,一个远程调用的对象。接着 stepped into 就行,它进来封装。
现在此处 Invoker:
Public Result invoke(Invocation invocation)throws RpcException{
Result result=null
首先得到的是最外层的 MockClusterInvoker,Invoker 时候又是 invoker.invoke,这里面又封装了 FailoverClusterInvoker。这些 clusterInvoker 其实就是 Invoker。当我们出现失败以后这是一个失败重试,重试到其他服务器。
继续执行,Invoker 里还会有。在 Invoker 执行的时候,集群执行的时候会发现这儿有一个方法叫 list:List<Invoker<T>>invokers=list(invocation
list 的作用是把想要执行的方法在注册中心找到,找到两个。一个是上一次的2.0版本,还有一个是1.0版本。然后接下来获取到配置的默认的负载均衡机制,获取到以后继续 doinvoke,继续进来,进入层层 Invoker 里,负载均衡拿到以后还有一个叫 select,能根据负载均衡策略(默认就是 random,按照权重进行负载,而 invoker,它随机选择一个 Invoker),选中执行2.0版本的方法,get user service 的 address 方法。
现在得到了 Invoker,有一个叫 invoker.invoke,继续执行。Invoker 里还有一些 Filter,真正要执行功能的时候封装了一些 Filter。这个 Filter 在最一开始代理对象里要用 Invoker 的时候,可以来封装 Filter。
比如要做缓存功能,有一个示例,示例里有一个结果缓存,如果想把结果缓存啊,可以配上 cache=“lru”,给代理对象加一个 Filter,如果还想做缓存,还想做 Mock,mock 就是有一个叫本地伪装,还想做这个功能,能有相关的 filter 介入,但是都没配这两个功能。所以一开始就来到了 invoker,invoker 选中了负载均衡以后,接下来就是又进入了 filter 的环节(各个统计信息),比如监控中心要统计一些信息,count 各种统计。
进入各种 Filter 的环节,Invoker 里明显看到有 Filter,同时 Filter 里还继续有封装。Invoker 里 dubboInvoker,还有其他的 filter,filter 里边又有其他的 filter,filter 里又有 Invoker,Invoker。相当于最终真正的目标方法把所有的 filter 都解除以后,就叫 dubboInvoke。
一步一步进入,来到一个 filter(protocolfilter),继续进入,在:return invoker.invoke(invocation)又要执行再来进入,还是 filter 来进入,进入以后呢,Result result=invoker.invoke(invacation),Invoker 又要执行,再来进入,是刚才那个 future filter,然后返回,再进入,来到 monitor 的 filter,相当于各种 filter 层层过滤。
在 return invoker.invoke(invocation )继续执行,接下来到抽象的 invoker 里。
doInvoker 继续执行,最终来到 dubboInvoker(打一个断点),这才是真正执行功能的。要执行哪个方法?
拿到方法的信息,将来它会拿到客户端,客户端在服务引用的时候暴露过一次,客户端相当于保存了要连上哪个服务。当前要连向
20882,找到客户端以后会发现有一个 currentClient.request,相当于客户端发起请求,发起请求以后获取请求的结果,然后返回.相当于就来到底层的调用,也就是已经来到了这个客户端了。客户端要进行调用,那就要进行底层的通信。发送请求, stepinto 进入,拿到客户端,发送请求进来,拿到通道发送请求,模拟出一个请求对象。
Req.setVersion(“2.0,0”)
Req.setTwoWay(true)
Req.setDate(request)
然后,给通道发送出去,这就是底层的请求发送方法。发送以后有一个返回,返回以后,get 得到最终请求的这个结果。这儿还有一个超时属性或方法执行超时,就会报错,超时了再来放行放。有第二次重试,换一个机器再试。
发现没有出错,那直接就出来了,出来拿到响应结果。在响应结果里,Response result 里封装了远程调用的两个返回的结果对象,拿到这个结果对象以后把这个封装一下,再来返回。整个 dubbo 一执行完以后,把整个结果还有进行各种解码编解码,然后返回,返回完了以后整个相当于就调用完了。最后是控制台进行功能打印。以上就是全部的步骤。
二、总结
调用步骤,主要就是这张原理图。
代理对象如果有要做其他功能,有 filter 介入。否则没有的话,用 Cluster,是来封装多个 Invoker 的,如果有多个 Invoker 的情况下,还能选一种负载均衡机制,而且调用错了,还会有重试。
负载均衡在调动期间还有其他的 filter 来介入,统计一些信息数据,当然最终真正执行功能的,由于是用 dubbo 协议来远程调用,所以说是 dubboInvoker 来进行调用。
而调用的底层是 client 发送请求,在client 的底层,就是用 Netty 的客户端连接目标端口的服务器来发送请求。服务器请求收到数据以后,就要解码来整个返回数据。
由代理对象交还。所以这是整个的调用完成。