10.发现到服务之后如何玩转调用的最简过程

上一篇文章中讲述了消费这么找到服务,怎么为后面的调用准备client与invoker。

这篇我们探讨下,当一个rpc服务真正发起调用时是怎样的,经历那些过程。

我们先截取一段服务发起调用时的调用栈,在截取调用栈之前我们先准备一个用例,有返回值的rpc调用,后面文章也会用到。

相关case代码

facade端的接口:

package com.code260.ss.dubbo.demov.facade.service;

import com.code260.ss.dubbo.demov.facade.bean.User;

/**
 * <一句话功能简述>
 * <功能详细描述>
 * 
 * @author  chen.simon
 * @version  [版本号, 2016-9-6]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public interface UserService
{
    public User queryUser(Integer id);
}

server端的实现:

package com.code260.ss.dubbo.demov.server.service.impl;

import java.util.Date;

import com.code260.ss.dubbo.demov.facade.bean.Team;
import com.code260.ss.dubbo.demov.facade.bean.User;
import com.code260.ss.dubbo.demov.facade.service.UserService;

/**
 * <一句话功能简述>
 * <功能详细描述>
 * 
 * @author  chen.simon
 * @version  [版本号, 2016-9-7]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class UserServiceImpl implements UserService
{
    
    /**
     * @param id
     * @return
     */
    @Override
    public User queryUser(Integer id)
    {
        User u = new User();
        u.setId(id);
        StringBuffer sb = new StringBuffer();
        String line = "aabbccddeeffgghhjji\n";
        int bodysize = 1 * 10 * 7;
        for (int i = 0 ; i <  bodysize / (line.length()); i++){
            sb.append(line);
        }
        u.setName(sb.toString());
        Team team = new Team();
        team.setId(100);
        team.setName("xx office");
        u.setTeam(team);
        System.out.println("Query user--" + id +"@" + new Date());
        return u;
    }
}

server端的node启动还是跟HelloService的公用:

package com.code260.ss.dubbo.demov.server.registercenter.zookeeper;

import java.io.IOException;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/com/code260/ss/dubbo/demov/server/conf/registercenter/zookeeper/applicationContextNode1.xml")
public class HelloServiceTestNode1
{

    @Test
    public void testSayHello()
    {
        try
        {
            System.out.println("zookeeper注册中心demo:I am node1:-)");
            System.in.read();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

server端的provider配置:

<dubbo:service interface="com.code260.ss.dubbo.demov.facade.service.UserService" ref="m00001.app001.xx.userService" filter="accesslog" 
    timeout="600000" token="123456"  connections="10">
        <dubbo:parameter key="accesslog" value="true" />
    </dubbo:service>
<bean id="m00001.app001.xx.userService" class="com.code260.ss.dubbo.demov.server.service.impl.UserServiceImpl" />

client端的test case:

package com.code260.ss.dubbo.demov.client.registercenter.zookeeper;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.code260.ss.dubbo.demov.facade.bean.User;
import com.code260.ss.dubbo.demov.facade.service.UserService;

/**
 * <一句话功能简述> <功能详细描述>
 * 
 * @author Chenxiaguang
 * @version [版本号, 2015-8-12]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/com/code260/ss/dubbo/demov/client/conf/registercenter/zookeeper/applicationContext.xml")
public class UserClientTest
{
    
    @Autowired
    private UserService userService;
    
    @Test
    public void testQueryUser()
    {
        User user = userService.queryUser(100);
        System.out.println(user.getName());
    }
}

Client端的consumer配置:

	<dubbo:reference id="userService" interface="com.code260.ss.dubbo.demov.facade.service.UserService" filter="cache,validation,deprecated,compatible" >
	    <!-- 能支持的全部cache定义在META-INF/dubbo/internal/com.alibaba.dubbo.cache.CacheFactory 当然你也可以遵循dubbo扩展点机制进行扩展。 -->
	    <!-- 何种类型的cache -->
	    <dubbo:parameter key="cache" value="lru" />
<!-- 	    <dubbo:parameter key="validation" value="JValidator"/> -->
	    <!-- 配置一个实现了javax.validation.spi.ValidationProvider<T>接口校验器 -->
<!-- 	    <dubbo:parameter key="jvalidation" value="org.hibernate.validator.HibernateValidator" />-->	    
	    <dubbo:method name="queryUser">
	        <dubbo:parameter key="deprecated" value="true" />
	    </dubbo:method>
<!--  	    <dubbo:parameter key="token" value="123456" /> -->
	</dubbo:reference>

服务发起调用时的调用栈

HeaderExchangeChannel.request(Object, int) line: 112	
HeaderExchangeClient.request(Object, int) line: 91	
DubboInvoker<T>.doInvoke(Invocation) line: 96	
DubboInvoker<T>(AbstractInvoker<T>).invoke(Invocation) line: 144	
CompatibleFilter.invoke(Invoker<?>, Invocation) line: 43	
ProtocolFilterWrapper$1.invoke(Invocation) line: 91	
DeprecatedFilter.invoke(Invoker<?>, Invocation) line: 51	
ProtocolFilterWrapper$1.invoke(Invocation) line: 91	
ValidationFilter.invoke(Invoker<?>, Invocation) line: 57	
ProtocolFilterWrapper$1.invoke(Invocation) line: 91	
CacheFilter.invoke(Invoker<?>, Invocation) line: 55	
ProtocolFilterWrapper$1.invoke(Invocation) line: 91	
MonitorFilter.invoke(Invoker<?>, Invocation) line: 75	
ProtocolFilterWrapper$1.invoke(Invocation) line: 91	
FutureFilter.invoke(Invoker<?>, Invocation) line: 53	
ProtocolFilterWrapper$1.invoke(Invocation) line: 91	
ConsumerContextFilter.invoke(Invoker<?>, Invocation) line: 48	
ProtocolFilterWrapper$1.invoke(Invocation) line: 91	
ListenerInvokerWrapper<T>.invoke(Invocation) line: 74	
RegistryDirectory$InvokerDelegete<T>(InvokerWrapper<T>).invoke(Invocation) line: 53	
FailoverClusterInvoker<T>.doInvoke(Invocation, List<Invoker<T>>, LoadBalance) line: 77	
FailoverClusterInvoker<T>(AbstractClusterInvoker<T>).invoke(Invocation) line: 227	
MockClusterInvoker<T>.invoke(Invocation) line: 72	
InvokerInvocationHandler.invoke(Object, Method, Object[]) line: 52	
proxy0.queryUser(Integer) line: not available	
UserClientTest.testQueryUser() line: 38

上面的栈展示了从UserClientTest.testQueryUser()这个case调用rpc服务到HeaderExchangeChannel.request请求远端服务的过程栈。

请求远端服务的方式是HeaderExchangeChannel.request(Object, int) line: 112,代码如下:

channel.send(req);

这个channel是:

com.alibaba.dubbo.remoting.transport.netty.NettyClient [/192.168.2.3:53474 -> /192.168.2.3:20880]

当然这是有返回值two way的服务调用方式,没有返回值像HelloService那种one way的略有差别。

整体流程

graph TD
A(1-为consumer服务生成的代理)-->B(2-分布式集群容错调用器)
B-->C(3-注册目录服务调用)
C-->D(4-调用链上的过滤器)
D-->E(5-rpc协议调用器DubboInvoker)
E-->F(6-HeaderExchangeClient交换层的client)
F-->G(7-网络层的NettyClient发送请求)

1处的为consumer服务生成的代理这个代理的生成过程分析可以参见前面的文章:06.消费者consumer侧 reference bean生成逻辑。

2-分布式集群容错调用器 后面文章讲。

4-调用链上的过滤器 后面文章讲。

此文主要是描述下consumer端发起调用的一个全貌,一个顶层堆栈流程。