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端发起调用的一个全貌,一个顶层堆栈流程。
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!