美文网首页dubbo
Dubbo之服务调用源码分析

Dubbo之服务调用源码分析

作者: loveFXX | 来源:发表于2020-08-04 11:56 被阅读0次

    dubbo整体设计具体可参考官网

    dubbo-framework.jpg
    服务引用,引用的是一个代理类。invoker通过InvokerInvocationHandler包装,然后通过JavassistProxyFactory#getProxy生成代理类。在调用也会首先经过InvokerInvocationHandler.invoker方法

    服务消费端调用流程

    1、InvokerInvocationHandler#invoke
    org.apache.dubbo.rpc.proxy.InvokerInvocationHandler#invoke


    image.png

    ①、这里会把method和args封装成RpcInvocation对象
    ②、调用invoker.invoke(RpcInvocation)方法
    ③、recreate()
    2、MockClusterInvoker#invoke
    org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker#invoke


    image.png
    image.png
    mock的处理:
    ①、没有mock

    ②、mock值是以force开头
    ③、fail-mock
    3、AbstractClusterInvoker#invoke
    org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke


    image.png
    ①、通过list从动态服务目录directory过滤出可执行invoker
    ②、得到负载均衡器RandomLoadBalance 基于权重随机算法
    image.png
    服务提供者URL不存在参数,默认是random
    ③、调用doInvoke
    list从动态服务目录directory过滤出可执行invoker

    1、AbstractClusterInvoker#list
    org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#list


    image.png

    2、AbstractDirectory#list
    org.apache.dubbo.rpc.cluster.directory.AbstractDirectory#list


    image.png
    3、RegistryDirectory#doList
    org.apache.dubbo.registry.integration.RegistryDirectory#doList
    image.png

    4、route
    org.apache.dubbo.rpc.cluster.RouterChain#route


    image.png
    动态服务目录中invokers赋值给finalInvokers,然后通过四种过滤routers进行遍历过滤
    ①、MockInvokersSelector
    org.apache.dubbo.rpc.cluster.router.mock.MockInvokersSelector#route
    image.png
    attachments属性值invocation.need.mock的处理
    org.apache.dubbo.rpc.cluster.router.mock.MockInvokersSelector#getNormalInvokers
    image.png
    不是mock协议
    ②、TagRouter标签路由处理
    org.apache.dubbo.rpc.cluster.router.tag.TagRouter#route
    image.png
    image.png

    ③、条件路由
    遍历conditionRouters条件路由规则
    org.apache.dubbo.rpc.cluster.router.condition.config.ListenableRouter#route


    image.png
    Cluster集群容错doInvoke

    集群FailoverClusterInvoker失败自动切换
    1、doInvoke
    org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke


    image.png
    image.png

    ①、根据随机算法、invocation调用select方法从copyInvokers得到invoker
    ②、得到的invoker放入invoked集合,表示已经选择过这个
    ③、选出的invoker设置到Rpc环境上下文中
    ④、调用选出的invoker的invoker方法
    2、select
    org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#select


    image.png
    image.png
    ①、获取 sticky 配置,sticky 表示粘滞连接。所谓粘滞连接是指让服务消费者尽可能的调用同一个服务提供者,除非该提供者挂了再进行切换
    ②、如果stickyInvoker有值且可用,就返回这个粘滞连接地址。
    ③、如果不可用,调用doSelect方法。
    ④、如果是粘滞连接,且stickyInvoker不可用。也会走doSelect方法,会把得到的invoker赋值给stickyInvoker

    2.1、doSelect
    org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#doSelect


    image.png
    ①、如果invokers只有一个,直接返回这个
    ②、如果有多个会通过loadbalance策略进行选择
    ③、如果在selected已经选择过的包含了经过loadbalance挑选出来的,会进行重新选择reselect
    ④、如果重新选择得到的是空,就是获取当前包含在selected的下一个
    3、invoke
    org.apache.dubbo.rpc.protocol.InvokerWrapper#invoke
    image.png
    4、invoke
    org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper.CallbackRegistrationInvoker#invoke
    image.png
    首先调用filterInvoker.invoke方法,得到asyncResult结果后,会回调调用filters过滤链ConsumerContextFilter、FutureFilter、MonitorFilter
    image.png
    5、buildInvokerChain
    调用filters的invoke方法,与4中的filterInvoker同属于CallbackRegistrationInvoker的属性值
    org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper#buildInvokerChain
    image.png
    调用ConsumerContextFilter的invoke,得到一个异步结果asyncResult
    ①、ConsumerContextFilter

    org.apache.dubbo.rpc.filter.ConsumerContextFilter#invoke
    设置RpcContext参数


    image.png
    image.png
    ②、FutureFilter
    org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter#invoke
    image.png
    ③、MonitorFilter
    org.apache.dubbo.monitor.support.MonitorFilter#invoke
    image.png
    设置一些监控信息
    6、invoke
    org.apache.dubbo.rpc.listener.ListenerInvokerWrapper#invoke
    image.png
    7、invoke
    org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker#invoke
    AsyncToSyncInvoker完成异步转同步,因为DubboInvoker的执行是异步非阻塞的,所以如果是同步调用,则会在此处阻塞,直到拿到响应结果。
    image.png
    如果invocation指定是同步的,则阻塞等待结果
    8、invoke
    org.apache.dubbo.rpc.protocol.AbstractInvoker#invoke
    image.png
    image.png
    image.png
    9、doInvoke
    org.apache.dubbo.rpc.protocol.dubbo.DubboInvoker#doInvoke
    image.png
    ①、为RpcInvocation设置path和version
    RpcInvocation [methodName=sayHello, parameterTypes=[class java.lang.String], arguments=[world], attachments={path=org.apache.dubbo.demo.DemoService, remote.application=dubbo-demo-consumer-application, interface=org.apache.dubbo.demo.DemoService, version=0.0.0}]
    

    ②、获取客户端ExchangeClient,如果客户端数量有多个则会轮训clients


    image.png

    isOneway为true,表示请求不需要拿结果,这里是false,需要拿结果
    获取当前方法的所配置的超时时间timeout,默认为1000,1秒
    异步去请求,得到一个CompletableFuture
    asyncRpcResult表示异步结果。responseFuture会完成后会调用asyncRpcResult中的方法,这里并不会阻塞,如果要达到阻塞的效果在外层使用asyncRpcResult去控制

    ExchangeClient客户端发送执行请求数据

    1、ReferenceCountExchangeClient
    org.apache.dubbo.rpc.protocol.dubbo.ReferenceCountExchangeClient#request(java.lang.Object, int)


    image.png

    2、HeaderExchangeClient
    org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeClient#request(java.lang.Object, int)


    image.png
    3、HeaderExchangeChannel
    org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeChannel#request(java.lang.Object, int)
    image.png

    4、AbstractPeer
    org.apache.dubbo.remoting.transport.AbstractPeer#send


    image.png
    5、AbstractClient
    org.apache.dubbo.remoting.transport.AbstractClient#send
    image.png
    6、NettyChannel
    org.apache.dubbo.remoting.transport.netty4.NettyChannel#send
    image.png
    到这里便调用到netty源码部分,进行数据传输
    服务消费端读取服务端返回数据

    1、channelRead
    org.apache.dubbo.remoting.transport.netty4.NettyClientHandler#channelRead


    image.png

    2、AbstractPeer#received
    org.apache.dubbo.remoting.transport.AbstractPeer#received


    image.png
    3、MultiMessageHandler#received
    org.apache.dubbo.remoting.transport.MultiMessageHandler#received
    image.png

    4、HeartbeatHandler#received
    org.apache.dubbo.remoting.exchange.support.header.HeartbeatHandler#received


    image.png
    image.png
    心跳请求、心跳响应处理,如果不是以上两种会继续往下走
    5、AllChannelHandler#received
    org.apache.dubbo.remoting.transport.dispatcher.all.AllChannelHandler#received
    image.png
    线程池去处理message
    6、ChannelEventRunnable
    org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable#run
    image.png
    7、DecodeHandler#received

    org.apache.dubbo.remoting.transport.DecodeHandler#received


    image.png
    8、HeaderExchangeHandler#received
    org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler#received
    image.png
    9、HeaderExchangeHandler#handleResponse
    HeaderExchangeHandler处理Response时,根据Response的id,可以查到DefaultFuture,然后调用DefaultFuture的complete方法,并设置DefaultFuture的值是Response。当处理请求Request时,会调用ExchangeHandlerAdapter的relpy方法
    org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler#handleResponse
    image.png
    10、DefaultFuture
    DefaultFuture在发送数据中,HeaderExchangeHandler会对当前请求添加一个DefaultFuture,并设置超时时间。最终会调用complete方法把响应传递给AsyncToSyncInvoker
    org.apache.dubbo.remoting.exchange.support.DefaultFuture#received(org.apache.dubbo.remoting.Channel, org.apache.dubbo.remoting.exchange.Response)
    image.png
    org.apache.dubbo.remoting.exchange.support.DefaultFuture#received
    image.png
    org.apache.dubbo.remoting.exchange.support.DefaultFuture#doReceived
    image.png
    org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter#FutureAdapter
    image.png

    服务提供端调用流程

    服务端提供者接收请求与服务消费者得到响应类似。
    首先经过NettyServerHandler,读取请求。最终会经过HeaderExchangeHandler
    处理Request数据,首先构造一个Response对象,然后调用ExchangeHandlerAdapter得到一个CompletionStage future,然后给future通过whenComplete绑定一个回调函数,当future执行完了之后,就可以从回调函数中得到ExchangeHandlerAdapter的执行结果,并把执行结果设置给Response对象,通过channel发送出去。
    1、ExchangeHandlerAdapter#reply
    org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter#reply


    image.png

    转成Invocation对象,可以反射执行方法了。并获取invoker


    image.png
    2、CallbackRegistrationInvoker#invoke
    org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper.CallbackRegistrationInvoker#invoke
    image.png
    EchoFilter、ClassLoaderFilter、GenericFilter、ContextFilter、TraceFilter、TimeoutFilter、MonitorFilter、ExceptionFilter
    ①、EchoFilter#invoke
    org.apache.dubbo.rpc.filter.EchoFilter#invoke
    image.png

    判断当前请求是不是一个回升测试,如果是,则不继续执行过滤器链
    ②、ClassLoaderFilter#invoke
    org.apache.dubbo.rpc.filter.ClassLoaderFilter#invoke


    image.png
    设置当前线程的classloader
    ③、GenericFilter#invoke
    org.apache.dubbo.rpc.filter.GenericFilter#invoke
    image.png
    把泛化调用发送过来的信息包装为RpcInvocation对象
    ④、ContextFilter#invoke
    org.apache.dubbo.rpc.filter.ContextFilter#invoke
    image.png
    image.png
    设置RpcContext.getContext()的参数
    ⑤、TraceFilter#invoke
    org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter#invoke
    image.png
    先执行下一个invoker的invoke方法,调用成功后Trace调用信息
    ⑥、TimeoutFilter#invoke
    org.apache.dubbo.rpc.filter.TimeoutFilter#invoke
    image.png

    只是记录了一下当前时间,当整个filter链都执行完了之后回调TimeoutFilter的onResponse方法时,会判断本次调用是否超时
    ⑦、MonitorFilter#invoke
    org.apache.dubbo.monitor.support.MonitorFilter#invoke


    image.png
    记录服务的执行次数
    ⑧、ExceptionFilter#invoke
    org.apache.dubbo.rpc.filter.ExceptionFilter#invoke
    image.png
    调用时没有做什么,在回调onResponse方法时,会对不同的异常进行处理
    3、InvokerWrapper#invoke
    org.apache.dubbo.rpc.protocol.InvokerWrapper#invoke
    image.png
    4、DelegateProviderMetaDataInvoker
    org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker#invoke
    image.png
    5、invoke
    org.apache.dubbo.rpc.proxy.AbstractProxyInvoker#invoke
    image.png
    6、doInvoke
    org.apache.dubbo.rpc.proxy.AbstractProxyInvoker#doInvoke
    image.png
    执行的proxy实例的方法。执行到这里便可以执行到服务提供的方法。
    为什么要用wrapper,这里不是代理接口,是直接基于某个对象proxy,进行代理

    dubbo服务提供者异常在服务消费者抛出

    捕获异常,保证结果为正常的AppResponse对象
    此时exception不为空,如果是正常返回exception是空的
    1、AbstractProxyInvoker#invoke
    org.apache.dubbo.rpc.proxy.AbstractProxyInvoker#invoke


    image.png

    2、newDefaultAsyncResult
    org.apache.dubbo.rpc.AsyncRpcResult#newDefaultAsyncResult


    image.png
    3、setException
    org.apache.dubbo.rpc.AppResponse#setException
    image.png
    4、recreate
    org.apache.dubbo.rpc.AppResponse#recreate
    image.png
    image.png

    服务消费端是在调用AppResponse的recreate方法重新得到一个结果,在recreate方法中会去判断AppResponse对象是否正常,也就是是否存在exception信息,如果存在,则直接throw这个exception。这样就做到了服务提供者异常在消费端抛出

    onResponse

    消费者端如果不存在这个抛出类
    org.apache.dubbo.rpc.filter.ExceptionFilter.ExceptionListener#onResponse


    image.png
    image.png
    image.png

    如果是检查异常、签名中出现异常、异常类和接口类位于同一jar文件中、是JDK异常、是dubbo异常则会直接抛出给消费者,如果不是以上几种,则会用RuntimeException进行包裹然后再抛出给消费者。这样处理可以避免消费者端不存在这个抛出类

    总结:

    Dubbo远程调用逻辑,是在服务导出和服务引用的基础上,其中的核心就是Invokers的调用链,这个Invoker执行链是在服务导出和引用构建的。在服务提供者和消费端请求和响应数据是通过netty或其他服务进行传输的。在这其中也处理了服务提供者异常在消费者抛出和如果消费者不存在异常类问题。当走到这里便可以看懂官网dubbo整体设计。

    相关文章

      网友评论

        本文标题:Dubbo之服务调用源码分析

        本文链接:https://www.haomeiwen.com/subject/qmtmrktx.html