服務提供者初始化完成之后反镇,對外暴露Exporter。服務消費者初始化完成之后送火,得到的是Proxy代理拳话,方法調用的時候就是調用代理。
服務消費者經過初始化之后种吸,得到的是一個動態(tài)代理類弃衍,InvokerInvocationHandler,包含MockClusterInvoker坚俗,MockClusterInvoker包含一個RegistryDirectory和FailoverClusterInvoker镜盯。
Java動態(tài)代理,每一個動態(tài)代理類都必須要實現InvocationHandler這個接口坦冠,并且每一個代理類的實例都關聯到了一個handler形耗,當我們通過代理對象調用一個方法的時候,這個方法就會被轉發(fā)為由實現了InvocationHandler這個接口的類的invoke方法來進行調用辙浑。
服務消費者發(fā)起調用請求
InvokerInvocationHandler實現了InvocationHandler接口激涤,當我們調用helloService.sayHello();
的時候,實際上會調用invoke()方法:
//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():
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方法:
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中,執(zhí)行調用
return doInvoke(invocation, invokers, loadbalance);
}
FailoverClusterInvoker.doInvoke():
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列表已發(fā)生變化.
//注意:如果列表發(fā)生了變化,那么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:
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():
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) {//異步的惭载,發(fā)送完需要得到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方法:
public ResponseFuture request(Object request, int timeout) throws RemotingException {
//這里的Channel是HeaderExchangeChannel
return channel.request(request, timeout);
}
進入HeaderExchangeChannel的request方法:
public ResponseFuture request(Object request, int timeout) throws RemotingException {
if (closed) {
throw new RemotingException(。拘泞。纷纫。);
}
//創(chuàng)建一個請求頭
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
//發(fā)送請求
channel.send(req);
}catch (RemotingException e) {
future.cancel();
throw e;
}
return future;
}
channel.send(req)
,首先會調用AbstractPeer的send方法:
//子類處理陪腌,接著是AbstractClient執(zhí)行發(fā)送
public void send(Object message) throws RemotingException {
send(message, url.getParameter(Constants.SENT_KEY, false));
}
AbstractClient執(zhí)行發(fā)送:
public void send(Object message, boolean sent) throws RemotingException {
//重連
if (send_reconnect && !isConnected()){
connect();
}
//先獲取Channel辱魁,是在NettyClient中實現的
Channel channel = getChannel();
//TODO getChannel返回的狀態(tài)是否包含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來繼續(xù)處理染簇,這里就把消息發(fā)送到服務端了:
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");
}
}
服務提供者處理并響應請求
服務端已經打開端口并監(jiān)聽請求的到來参滴,當服務消費者發(fā)送調用請求的時候,經過Netty的處理后會到dubbo中的codec相關方法中先進行解碼剖笙,入口是NettyCodecAdapter.messageReceived()
卵洗,關于這個方法的代碼在dubbo編解碼的那篇文章中已經分析過,不再重復弥咪。經過解碼之后过蹂,會進入到NettyHandler.messageReceived()方法:
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方法:
public void received(Channel ch, Object msg) throws RemotingException {
if (closed) {
return;
}
//這里是MultiMessageHandler
handler.received(ch, msg);
}
進入MultiMessageHandler的received方法:
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方法:
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);
}
繼續(xù)進入AllChannelHandler的received方法:
public void received(Channel channel, Object message) throws RemotingException {
//獲取線程池執(zhí)行
ExecutorService cexecutor = getExecutorService();
try {
//handler是DecodeHandler
cexecutor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
} catch (Throwable t) { }
}
這里會去啟動新線程執(zhí)行ChannelEventRunnable的run方法聚至,接著去調用DecodeHandler的received方法:
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方法:
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,發(fā)送響應信息
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);
}
}
先看下處理請求扳躬,并構造響應信息:
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方法:
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());
//執(zhí)行調用,然后返回結果
return invoker.invoke(inv);
}
throw new RemotingException(贷币。击胜。。);
}
先看下getInvoker獲取Invoker:
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();
}
再看執(zhí)行調用invoker.invoke(inv);
辰斋,會先進入InvokerWrapper:
public Result invoke(Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}
接著進入AbstractProxyInvoker:
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實例:
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方法:
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藕夫,發(fā)送響應信息
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);
}
}
解析完請求,構造完響應消息丁逝,就開始發(fā)送響應了,channel.send(response);
汁胆,先經過AbstractPeer:
public void send(Object message) throws RemotingException {
//NettyChannel
send(message, url.getParameter(Constants.SENT_KEY, false));
}
進入NettyChannel中,進行響應消息的發(fā)送:
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()處理:
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方法:
public void received(Channel ch, Object msg) throws RemotingException {
if (closed) {
return;
}
//MultiMessageHandler
handler.received(ch, msg);
}
進入MultiMessageHandler:
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铡恕,根據不同類型進行處理:
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:
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:
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:
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 () 方法:
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方法:
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中,這里繼續(xù)執(zhí)行卤橄,然后執(zhí)行Filter绿满,最后返回到InvokerInvocationHandler.invoker()方法中,方法得到調用結果窟扑,結束喇颁!
注意:
消費者端的DubboInvoker發(fā)起請求后,后續(xù)的邏輯是異步的或是指定超時時間內阻塞的嚎货,直到得到響應結果后橘霎,繼續(xù)執(zhí)行DubboInvoker中邏輯。
對于異步請求時殖属,消費者得到Future茎毁,其余邏輯均是異步的。
消費者還可以通過設置async忱辅、sent、return來調整處理邏輯谭溉,async指異步還是同步請求墙懂,sent指是否等待請求消息發(fā)出即阻塞等待是否成功發(fā)出請求、return指是否忽略返回值即但方向通信扮念,一般異步時使用以減少Future對象的創(chuàng)建和管理成本损搬。