服务提供者初始化完成之后,对外暴露Exporter。服务消费者初始化完成之后,得到的是Proxy代理,方法调用的时候就是调用代理。

服务消费者经过初始化之后,得到的是一个动态代理类,InvokerInvocationHandler,包含MockClusterInvoker,MockClusterInvoker包含一个RegistryDirectory和FailoverClusterInvoker。

Java动态代理,每一个动态代理类都必须要实现InvocationHandler这个接口,并且每一个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法就会被转发为由实现了InvocationHandler这个接口的类的invoke方法来进行调用。

服务消费者发起调用请求

InvokerInvocationHandler实现了InvocationHandler接口,当我们调用helloService.sayHello();的时候,实际上会调用invoke()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//proxy是代理的真实对象
//method调用真实对象的方法
//args调用真实对象的方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法名sayHello
String methodName = method.getName();
//参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
//invoker是MockClusterInvoker
//首先new RpcInvocation
//然后invoker.invoke
//最后recreate
//返回结果
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}

先看下new RpcInvocation,Invocation是会话域,它持有调用过程中的变量,比如方法名,参数类型等。

接着是invoker.invoke(),这里invoker是MockClusterInvoker,进入MockClusterInvoker.invoker():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public Result invoke(Invocation invocation) throws RpcException {
Result result = null;
//获取mock属性的值,我们没有配置,默认false
String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
if (value.length() == 0 || value.equalsIgnoreCase("false")){
//这里invoker是FailoverClusterInvoker
result = this.invoker.invoke(invocation);
} else if (value.startsWith("force")) {
//force:direct mock
result = doMockInvoke(invocation, null);
} else {
//fail-mock
try {
result = this.invoker.invoke(invocation);
}catch (RpcException e) {
if (e.isBiz()) {
throw e;
} else {
result = doMockInvoke(invocation, e);
}
}
}
return result;
}

result = this.invoker.invoke(invocation);这里invoker是FailoverClusterInvoker,会首先进入AbstractClusterInvoker的invoke方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public Result invoke(final Invocation invocation) throws RpcException {
//检查是否被销毁
checkWheatherDestoried();
LoadBalance loadbalance;
//根据invocation中的参数来获取所有的invoker列表
List<Invoker<T>> invokers = list(invocation);
if (invokers != null && invokers.size() > 0) {
//我们没有配置负载均衡的参数,默认使用random
//这里得到的是RandomLoadBalance
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
.getMethodParameter(invocation.getMethodName(),Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
} else {
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
}
//如果是异步操作默认添加invocation id
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
//这里是子类实现,FailoverClusterInvoker中,执行调用
return doInvoke(invocation, invokers, loadbalance);
}

FailoverClusterInvoker.doInvoke():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
List<Invoker<T>> copyinvokers = invokers;
//检查invokers是否为空
checkInvokers(copyinvokers, invocation);
//重试次数
int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}
// retry loop.
RpcException le = null; // last exception.
//已经调用过的invoker
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyinvokers.size()); // invoked invokers.
Set<String> providers = new HashSet<String>(len);
for (int i = 0; i < len; i++) {
//重试时,进行重新选择,避免重试时invoker列表已发生变化.
//注意:如果列表发生了变化,那么invoked判断会失效,因为invoker示例已经改变
if (i > 0) {
checkWheatherDestoried();
copyinvokers = list(invocation);
//重新检查一下
checkInvokers(copyinvokers, invocation);
}
//使用负载均衡选择invoker.(负载均衡咱先不做解释)
Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
invoked.add(invoker);
//添加到以调用过的列表中
RpcContext.getContext().setInvokers((List)invoked);
try {
//开始调用,返回结果
Result result = invoker.invoke(invocation);
return result;
} catch (RpcException e) {。。。 } finally {
providers.add(invoker.getUrl().getAddress());
}
}
throw new RpcException(。。。);
}

Result result = invoker.invoke(invocation);调用并返回结果,会首先进入InvokerWrapper,然后进入ListenerInvokerWrapper的invoke方法,接着进入AbstractInvoker的invoke:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public Result invoke(Invocation inv) throws RpcException {
if(destroyed) {
throw new RpcException(。。。);
}
//转成RpcInvocation
RpcInvocation invocation = (RpcInvocation) inv;
invocation.setInvoker(this);
if (attachment != null && attachment.size() > 0) {
invocation.addAttachmentsIfAbsent(attachment);
}
Map<String, String> context = RpcContext.getContext().getAttachments();
if (context != null) {
invocation.addAttachmentsIfAbsent(context);
}
if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)){
invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
}
//异步的话,需要添加id
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
try {
//这里是DubboInvoker
return doInvoke(invocation);
} catch (InvocationTargetException e) { }
}

DubboInvoker.doInvoke():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
protected Result doInvoke(final Invocation invocation) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
final String methodName = RpcUtils.getMethodName(invocation);
inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
inv.setAttachment(Constants.VERSION_KEY, version);

ExchangeClient currentClient;
//在初始化的时候,引用服务的过程中会保存一个连接到服务端的Client
if (clients.length == 1) {
currentClient = clients[0];
} else {
currentClient = clients[index.getAndIncrement() % clients.length];
}
try {
//异步标志
boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
//单向标志
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY,Constants.DEFAULT_TIMEOUT);
//单向的,反送完不管结果
if (isOneway) {
boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
currentClient.send(inv, isSent);
RpcContext.getContext().setFuture(null);
return new RpcResult();
} else if (isAsync) {//异步的,发送完需要得到Future
ResponseFuture future = currentClient.request(inv, timeout) ;
RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
return new RpcResult();
} else {//同步调用,我们这里使用的这种方式
RpcContext.getContext().setFuture(null);
//HeaderExchangeClient
return (Result) currentClient.request(inv, timeout).get();
}
} catch (TimeoutException e) {。。。}
}

我们这里使用的是同步调用,看(Result) currentClient.request(inv, timeout).get();方法,这里的client是ReferenceCountExchangeClient,直接调用HeaderExchangeClient的request方法:

1
2
3
4
public ResponseFuture request(Object request, int timeout) throws RemotingException {
//这里的Channel是HeaderExchangeChannel
return channel.request(request, timeout);
}

进入HeaderExchangeChannel的request方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public ResponseFuture request(Object request, int timeout) throws RemotingException {
if (closed) {
throw new RemotingException(。。。);
}
//创建一个请求头
Request req = new Request();
req.setVersion("2.0.0");
req.setTwoWay(true);
//这里request参数里面保存着
//methodName = "sayHello"
//parameterTypes = {Class[0]@2814}
//arguments = {Object[0]@2768}
//attachments = {HashMap@2822} size = 4
//invoker = {DubboInvoker@2658}
req.setData(request);
DefaultFuture future = new DefaultFuture(channel, req, timeout);
try{
//这里的channel是NettyClient
//发送请求
channel.send(req);
}catch (RemotingException e) {
future.cancel();
throw e;
}
return future;
}

channel.send(req),首先会调用AbstractPeer的send方法:

1
2
3
4
//子类处理,接着是AbstractClient执行发送
public void send(Object message) throws RemotingException {
send(message, url.getParameter(Constants.SENT_KEY, false));
}

AbstractClient执行发送:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void send(Object message, boolean sent) throws RemotingException {
//重连
if (send_reconnect && !isConnected()){
connect();
}
//先获取Channel,是在NettyClient中实现的
Channel channel = getChannel();
//TODO getChannel返回的状态是否包含null需要改进
if (channel == null || ! channel.isConnected()) {
throw new RemotingException(this, "message can not send, because channel is closed . url:" + getUrl());
}
channel是NettyChannel
channel.send(message, sent);
}

channel.send(message, sent);首先经过AbstractChannel的send方法处理,只是判断是否关闭了,然后是NettyChannel的send来继续处理,这里就把消息发送到服务端了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void send(Object message, boolean sent) throws RemotingException {
super.send(message, sent);

boolean success = true;
int timeout = 0;
try {
//交给netty处理
ChannelFuture future = channel.write(message);
if (sent) {
timeout = getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
success = future.await(timeout);
}
Throwable cause = future.getCause();
if (cause != null) {
throw cause;
}
} catch (Throwable e) {
throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
}

if(! success) {
throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress()
+ "in timeout(" + timeout + "ms) limit");
}
}

服务提供者处理并响应请求

服务端已经打开端口并监听请求的到来,当服务消费者发送调用请求的时候,经过Netty的处理后会到dubbo中的codec相关方法中先进行解码,入口是NettyCodecAdapter.messageReceived(),关于这个方法的代码在dubbo编解码的那篇文章中已经分析过,不再重复。经过解码之后,会进入到NettyHandler.messageReceived()方法:

1
2
3
4
5
6
7
8
9
10
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
//获取channel
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);
try {
//这里handler是NettyServer
handler.received(channel, e.getMessage());
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
}
}

接着会进入AbstractPeer的received方法:

1
2
3
4
5
6
7
public void received(Channel ch, Object msg) throws RemotingException {
if (closed) {
return;
}
//这里是MultiMessageHandler
handler.received(ch, msg);
}

进入MultiMessageHandler的received方法:

1
2
3
4
5
6
7
8
9
10
11
12
public void received(Channel channel, Object message) throws RemotingException {
//是多消息的话,使用多消息处理器处理
if (message instanceof MultiMessage) {
MultiMessage list = (MultiMessage)message;
for(Object obj : list) {
handler.received(channel, obj);
}
} else {
//这里是HeartbeatHandler
handler.received(channel, message);
}
}

进入HeartbeatHandler的received方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void received(Channel channel, Object message) throws RemotingException {
setReadTimestamp(channel);
//心跳请求处理
if (isHeartbeatRequest(message)) {
Request req = (Request) message;
if (req.isTwoWay()) {
Response res = new Response(req.getId(), req.getVersion());
res.setEvent(Response.HEARTBEAT_EVENT);
channel.send(res);
}
return;
}
//心跳回应消息处理
if (isHeartbeatResponse(message)) {
return;
}
//这里是AllChannelHandler
handler.received(channel, message);
}

继续进入AllChannelHandler的received方法:

1
2
3
4
5
6
7
8
public void received(Channel channel, Object message) throws RemotingException {
//获取线程池执行
ExecutorService cexecutor = getExecutorService();
try {
//handler是DecodeHandler
cexecutor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
} catch (Throwable t) { }
}

这里会去启动新线程执行ChannelEventRunnable的run方法,接着去调用DecodeHandler的received方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void received(Channel channel, Object message) throws RemotingException {
//不清楚啥意思
if (message instanceof Decodeable) {
decode(message);
}
//解码请求类型
if (message instanceof Request) {
decode(((Request)message).getData());
}
//解码响应类型
if (message instanceof Response) {
decode( ((Response)message).getResult());
}
//解码之后到HeaderExchangeHandler中处理
handler.received(channel, message);
}

解码之后到HeaderExchangeHandler的received方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public void received(Channel channel, Object message) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
//request类型的消息
if (message instanceof Request) {
Request request = (Request) message;
if (request.isEvent()) {//判断心跳还是正常请求
// 处理心跳
handlerEvent(channel, request);
} else {//正常的请求
//需要返回
if (request.isTwoWay()) {
//处理请求,并构造响应信息
Response response = handleRequest(exchangeChannel, request);
//NettyChannel,发送响应信息
channel.send(response);
} else {//不需要返回的处理
handler.received(exchangeChannel, request.getData());
}
}
} else if (message instanceof Response) {//response类型的消息
handleResponse(channel, (Response) message);
} else if (message instanceof String) {
if (isClientSide(channel)) {
Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
} else {//telnet类型
String echo = handler.telnet(channel, (String) message);
if (echo != null && echo.length() > 0) {
channel.send(echo);
}
}
} else {
handler.received(exchangeChannel, message);
}
} finally {
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
}

先看下处理请求,并构造响应信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Response handleRequest(ExchangeChannel channel, Request req) throws RemotingException {
Response res = new Response(req.getId(), req.getVersion());
if (req.isBroken()) {
Object data = req.getData();

String msg;
if (data == null) msg = null;
else if (data instanceof Throwable) msg = StringUtils.toString((Throwable) data);
else msg = data.toString();
res.setErrorMessage("Fail to decode request due to: " + msg);
res.setStatus(Response.BAD_REQUEST);

return res;
}
// find handler by message class.
Object msg = req.getData();
try {
//处理请求数据,handler是DubboProtocol中的new的一个ExchangeHandlerAdapter
Object result = handler.reply(channel, msg);
res.setStatus(Response.OK);
res.setResult(result);
} catch (Throwable e) { }
return res;
}

进入DubboProtocol中的ExchangeHandlerAdapter的replay方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
if (message instanceof Invocation) {
//Invocation中保存着方法名等
Invocation inv = (Invocation) message;
//获取Invoker
Invoker<?> invoker = getInvoker(channel, inv);
//如果是callback 需要处理高版本调用低版本的问题
if (Boolean.TRUE.toString().equals(inv.getAttachments().get(IS_CALLBACK_SERVICE_INVOKE))){
String methodsStr = invoker.getUrl().getParameters().get("methods");
boolean hasMethod = false;
if (methodsStr == null || methodsStr.indexOf(",") == -1){
hasMethod = inv.getMethodName().equals(methodsStr);
} else {
String[] methods = methodsStr.split(",");
for (String method : methods){
if (inv.getMethodName().equals(method)){
hasMethod = true;
break;
}
}
}
if (!hasMethod){
return null;
}
}
RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
//执行调用,然后返回结果
return invoker.invoke(inv);
}
throw new RemotingException(。。。);
}

先看下getInvoker获取Invoker:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException{
boolean isCallBackServiceInvoke = false;
boolean isStubServiceInvoke = false;
int port = channel.getLocalAddress().getPort();
String path = inv.getAttachments().get(Constants.PATH_KEY);
//如果是客户端的回调服务.
isStubServiceInvoke = Boolean.TRUE.toString().equals(inv.getAttachments().get(Constants.STUB_EVENT_KEY));
if (isStubServiceInvoke){
port = channel.getRemoteAddress().getPort();
}
//callback
isCallBackServiceInvoke = isClientSide(channel) && !isStubServiceInvoke;
if(isCallBackServiceInvoke){
path = inv.getAttachments().get(Constants.PATH_KEY)+"."+inv.getAttachments().get(Constants.CALLBACK_SERVICE_KEY);
inv.getAttachments().put(IS_CALLBACK_SERVICE_INVOKE, Boolean.TRUE.toString());
}
String serviceKey = serviceKey(port, path, inv.getAttachments().get(Constants.VERSION_KEY), inv.getAttachments().get(Constants.GROUP_KEY));
//从之前缓存的exporterMap中查找Exporter
//key:dubbo.common.hello.service.HelloService:20880
DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey);

if (exporter == null)
throw new RemotingException(。。。);
//得到Invoker,返回
return exporter.getInvoker();
}

再看执行调用invoker.invoke(inv);,会先进入InvokerWrapper:

1
2
3
public Result invoke(Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}

接着进入AbstractProxyInvoker:

1
2
3
4
5
6
7
public Result invoke(Invocation invocation) throws RpcException {
try {
//先doInvoke
//然后封装成结果返回
return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
} catch (InvocationTargetException e) {。。。}
}

这里的doInvoke是在JavassistProxyFactory中的AbstractProxyInvoker实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper类不能正确处理带$的类名
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
//这里就调用了具体的方法
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}

消息处理完后返回到HeaderExchangeHandler的received方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public void received(Channel channel, Object message) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
//request类型的消息
if (message instanceof Request) {
Request request = (Request) message;
if (request.isEvent()) {//判断心跳还是正常请求
// 处理心跳
handlerEvent(channel, request);
} else {//正常的请求
//需要返回
if (request.isTwoWay()) {
//处理请求,并构造响应信息,这在上面已经解析过了
Response response = handleRequest(exchangeChannel, request);
//NettyChannel,发送响应信息
channel.send(response);
} else {//不需要返回的处理
handler.received(exchangeChannel, request.getData());
}
}
} else if (message instanceof Response) {//response类型的消息
handleResponse(channel, (Response) message);
} else if (message instanceof String) {
if (isClientSide(channel)) {
Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
} else {//telnet类型
String echo = handler.telnet(channel, (String) message);
if (echo != null && echo.length() > 0) {
channel.send(echo);
}
}
} else {
handler.received(exchangeChannel, message);
}
} finally {
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
}

解析完请求,构造完响应消息,就开始发送响应了,channel.send(response);,先经过AbstractPeer:

1
2
3
4
public void send(Object message) throws RemotingException {
//NettyChannel
send(message, url.getParameter(Constants.SENT_KEY, false));
}

进入NettyChannel中,进行响应消息的发送:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void send(Object message, boolean sent) throws RemotingException {
//AbstractChannel的处理
super.send(message, sent);

boolean success = true;
int timeout = 0;
try {
ChannelFuture future = channel.write(message);
if (sent) {
timeout = getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
success = future.await(timeout);
}
Throwable cause = future.getCause();
if (cause != null) {
throw cause;
}
} catch (Throwable e) {
throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
}

if(! success) {
throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress()
+ "in timeout(" + timeout + "ms) limit");
}
}

消费者接受到服务端返回的响应后的处理

服务提供者端接收到消费者端的请求并处理之后,返回给消费者端,消费者这边接受响应的入口跟提供者差不多,也是NettyCodecAdapter.messageReceived(),经过解码,到NettyHandler.messageReceived()处理:

1
2
3
4
5
6
7
8
9
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);
try {
//NettyClient
handler.received(channel, e.getMessage());
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
}
}

先经过AbstractPeer的received方法:

1
2
3
4
5
6
7
public void received(Channel ch, Object msg) throws RemotingException {
if (closed) {
return;
}
//MultiMessageHandler
handler.received(ch, msg);
}

进入MultiMessageHandler:

1
2
3
4
5
6
7
8
9
10
11
public void received(Channel channel, Object message) throws RemotingException {
if (message instanceof MultiMessage) {
MultiMessage list = (MultiMessage)message;
for(Object obj : list) {
handler.received(channel, obj);
}
} else {
//HeartbeatHandler
handler.received(channel, message);
}
}

进入HeartbeatHandler,根据不同类型进行处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void received(Channel channel, Object message) throws RemotingException {
setReadTimestamp(channel);
if (isHeartbeatRequest(message)) {
Request req = (Request) message;
if (req.isTwoWay()) {
Response res = new Response(req.getId(), req.getVersion());
res.setEvent(Response.HEARTBEAT_EVENT);
channel.send(res);
if (logger.isInfoEnabled()) {
int heartbeat = channel.getUrl().getParameter(Constants.HEARTBEAT_KEY, 0);
if(logger.isDebugEnabled()) {
logger.debug("Received heartbeat from remote channel " + channel.getRemoteAddress()
+ ", cause: The channel has no data-transmission exceeds a heartbeat period"
+ (heartbeat > 0 ? ": " + heartbeat + "ms" : ""));
}
}
}
return;
}
if (isHeartbeatResponse(message)) {
if (logger.isDebugEnabled()) {
logger.debug(
new StringBuilder(32)
.append("Receive heartbeat response in thread ")
.append(Thread.currentThread().getName())
.toString());
}
return;
}
//AllChannelHandler
handler.received(channel, message);
}

进入AllChannelHandler:

1
2
3
4
5
6
7
8
public void received(Channel channel, Object message) throws RemotingException {
ExecutorService cexecutor = getExecutorService();
try {
cexecutor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
} catch (Throwable t) {
throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
}
}

然后在新线程,ChannelEventRunnable的run方法中进入DecodeHandler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void received(Channel channel, Object message) throws RemotingException {
if (message instanceof Decodeable) {
decode(message);
}

if (message instanceof Request) {
decode(((Request)message).getData());
}
//这里进行response类型的处理
if (message instanceof Response) {
decode( ((Response)message).getResult());
}

handler.received(channel, message);
}

进入处理response的decode方法,进行解码response:

1
2
3
4
5
6
7
private void decode(Object message) {
if (message != null && message instanceof Decodeable) {
try {
((Decodeable)message).decode();
} catch (Throwable e) {。。。} // ~ end of catch
} // ~ end of if
}

接着会进入HeaderExchangerHandler.received () 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public void received(Channel channel, Object message) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
if (message instanceof Request) {
Request request = (Request) message;
if (request.isEvent()) {
handlerEvent(channel, request);
} else {
if (request.isTwoWay()) {
Response response = handleRequest(exchangeChannel, request);
channel.send(response);
} else {
handler.received(exchangeChannel, request.getData());
}
}
} else if (message instanceof Response) {
//这里处理response消息
handleResponse(channel, (Response) message);
} else if (message instanceof String) {
if (isClientSide(channel)) { Exception } else {
String echo = handler.telnet(channel, (String) message);
if (echo != null && echo.length() > 0) {
channel.send(echo);
}
}
} else {
handler.received(exchangeChannel, message);
}
} finally {
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
}

handleResponse方法:

1
2
3
4
5
static void handleResponse(Channel channel, Response response) throws RemotingException {
if (response != null && !response.isHeartbeat()) {
DefaultFuture.received(channel, response);
}
}

这一步设置response到消费者请求的Future中,以供消费者通过DefaultFuture.get()取得提供者的响应,此为同步转异步重要一步,且请求超时也由DefaultFuture控制。

然后就是return (Result) currentClient.request(inv, timeout).get();在DubboInvoker中,这里继续执行,然后执行Filter,最后返回到InvokerInvocationHandler.invoker()方法中,方法得到调用结果,结束!

注意:

消费者端的DubboInvoker发起请求后,后续的逻辑是异步的或是指定超时时间内阻塞的,直到得到响应结果后,继续执行DubboInvoker中逻辑。

对于异步请求时,消费者得到Future,其余逻辑均是异步的。

消费者还可以通过设置async、sent、return来调整处理逻辑,async指异步还是同步请求,sent指是否等待请求消息发出即阻塞等待是否成功发出请求、return指是否忽略返回值即但方向通信,一般异步时使用以减少Future对象的创建和管理成本。

Dubbo中服务消费者和服务提供者之间的请求和响应过程的更多相关文章

  1. dubbo rest服务(消费者) java.lang.ClassNotFoundException: org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine 错误问题

    1.版本 dubbo 2.7.3 2.描述 java.lang.ClassNotFoundException: org.jboss.resteasy.client.jaxrs.engines.Apac ...

  2. springcloud的服务提供者与服务消费者

    1.说明 springcloud中由服务消费者调用服务提供者一共有两种方法rest和feign 2.feign (1)使用feign的方式进行服务调,搭建服务提供者. 创建一个web项目(服务提供者) ...

  3. RPC原来就是Socket——RPC框架到dubbo的服务动态注册,服务路由,负载均衡演化

    序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用.然我们自己动手从0开始写一个rpc功能以及实 ...

  4. 一.把传统服务做成dubbo分布式服务架构的步骤

    1.把传统服务按照一定原则(根据项目的业务逻辑和场景)拆分成多个服务(主要服务是服务提供者和服务消费者,服务提供者或服务消费者的公共部分也可以拆分成其他服务,如公共DAO.公共工具类.公共实体,公共w ...

  5. Dubbo中订阅和通知解析

    Dubbo中关于服务的订阅和通知主要发生在服务提供方暴露服务的过程和服务消费方初始化时候引用服务的过程中. 2345678910111213141516171819 public <T> ...

  6. Java微服务(二):服务消费者与提供者搭建

    本文接着上一篇写的<Java微服务(一):dubbo-admin控制台的使用>,上篇文章介绍了docker,zookeeper环境的安装,并参考dubbo官网演示了dubbo-admin控 ...

  7. Dubbo之服务暴露

    前言 本文 Dubbo 使用版本2.7.5 Dubbo 通过使用dubbo:service配置或@service在解析完配置后进行服务暴露,供服务消费者消费. Dubbo 的服务暴露有两种: 远程暴露 ...

  8. Dubbo中的统一契约是如何实现的?

    写在前面 之前,很多小伙伴私信我:如何才能快速的掌握Dubbo的核心原理和源码.所以,我写了一篇<我是如何在短期内快速掌握Dubbo的原理和源码的(纯干货)?>.对于Dubbo的源码解析系 ...

  9. 【面试普通人VS高手系列】Dubbo的服务请求失败怎么处理?

    今天分享的面试题,几乎是90%以上的互联网公司都会问到的问题. "Dubbo的服务请求失败怎么处理"? 对于这个问题,我们来看一下普通人和高手的回答. 普通人: 嗯- 我记得, D ...

随机推荐

  1. 如何通过jQuery获取一个没有定高度的元素---------的自适应高度(offsetHeight的正确使用方法)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. candy(贪心)

    [题目] There are N children standing in a line. Each child is assigned a rating value. You are giving ...

  3. 转载 jQueryEasyUI Messager基本使用

    http://www.cnblogs.com/libingql/archive/2011/07/17/2109020.html 一.jQueryEasyUI下载地址 http://www.jeasyu ...

  4. CentOS6.5 64位下安装部署Ansible

    这里使用的软件包为一下版本 Python-2.7.12.tgz pip-9.0.1.tar.gz ansible-2.2.0.0.tar.gz 其他依赖包使用pip方式安装 方便说明做以下设定: 控制 ...

  5. Git的fast forward和no fast forward和 three way merge 以及squash(聚合)

    github上上传了版本库https://github.com/ChuckGitMerge   包括merge和rebase 没时间画图,貌似也不太会用画图工具,先写了一个文字版本的 更新:2015年 ...

  6. WebApi PUT、DELETE请求时出现405 - 不允许用于访问此页的 HTTP 谓词。

    开发时,新建WebApi项目需要用到Restful规范,此时请求有POST\PUT\DELETE\GET等请求 此时需要在web.config中加入 <system.webServer> ...

  7. RabbitMQ 安装 Your installed version of Erlang (6.2) is too old. Please install a more recent version.

    windows安装RabbitMQ时在安装完Erlang语言开发包后,再安装RabbitMQ时报错: Your installed version of Erlang (6.2) is too old ...

  8. js中几种实用的跨域方法原理详解【转】

    源地址:http://www.cnblogs.com/2050/p/3191744.html 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通 ...

  9. API文档模板

    接口说明: 登录接口 修订历史: 版本号 制定人 修订日期 0.0.2 zenghui 2017-09-27 0.0.1 zanshan 2017-02-20 URL: http://xxx.xx.c ...

  10. my views--软件工程、python

    这是大三第二学期开的一门课,由吴世枫老师和王韬助教教的. 大一开了C语言,大二开了java.matlab,而用得最多的应该是学java顺便学会的C++了.matlab在实训和数学建模用了多次,尤其是数 ...