dubbo source code analysis - service invocation process - Notes

Process flow chart of consumer call Calling process of consumer Consumer interface example: Process of receiving message at server NettyHandler. messa...
NettyHandler. messageReceived
ExchangeHandlerAdaptive.replay(DubboProtocol)
Process flow chart of consumer call

Calling process of consumer

Consumer interface example:

Process of receiving message at server

NettyHandler. messageReceived

  • When receiving messages, use NettyHandler.messageReceived as the entry
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler); try { handler.received(channel, e.getMessage()); } finally { NettyChannel.removeChannelIfDisconnected(ctx.getChannel()); } }

handler.received

  • What is this handler? Remember when the service was released, a series of handlers were assembled? The code is as follows

HeaderExchanger.bind

public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException { return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler)))); }

NettyServer

  • Then in Nettyserver, multiple handler s are wrap ped
public NettyServer(URL url, ChannelHandler handler) throws RemotingException { super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME))); } protected ChannelHandler wrapInternal(ChannelHandler handler, URL url) { return new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class) .getAdaptiveExtension().dispatch(handler, url))); }

So the handler processing chain of the server is

  • MultiMessageHandler(HeartbeatHandler(AllChannelHandler(DecodeHandler)))
  • MultiMessageHandler: composite message processing
  • Heartbeat handler: heartbeat message processing, receiving heartbeat and sending heartbeat response
  • AllChannelHandler: business thread transformation processor, encapsulating received messages into ChannelEventRunnable executable tasks for thread pool processing
  • DecodeHandler: business decoding processor

HeaderExchangeHandler.received

  • There are three ways to process the request response in the interaction layer:
    1. handlerRequest, two-way request
    2. handler.received one way request
    3. handleResponse response message
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) { // handle 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) { 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()); logger.error(e.getMessage(), e); } 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); } }

handleRequest

  • Process request and return response
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 { // handle data. Object result = handler.reply(channel, msg); res.setStatus(Response.OK); res.setResult(result); } catch (Throwable e) { res.setStatus(Response.SERVICE_ERROR); res.setErrorMessage(StringUtils.toString(e)); } return res; }

ExchangeHandlerAdaptive.replay(DubboProtocol)

  • Call the ExchangeHandlerAdaptive.replay method defined in DubboProtocol to process messages
private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() { public Object reply(ExchangeChannel channel, Object message) throws RemotingException { invoker.invoke(inv); }
  • Which class will invoker.invoke call next?
  • Do you remember the wrapper for invoker when publishing local methods in RegistryDirectory?
  • The original invoker is packaged through invokerdelegent. What is the original invoker?
  • It is a dynamic proxy generated by JavassistProxyFactory.
  • So the invoker here should be:

Filter(Listener(InvokerDelegete(AbstractProxyInvoker (Wrapper.invokeMethod)))

  • The code to generate the invoker from RegistryDirectory is as follows:
private <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker){ String key = getCacheKey(originInvoker); ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key); if (exporter == null) { synchronized (bounds) { exporter = (ExporterChangeableWrapper<T>) bounds.get(key); if (exporter == null) { final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker)); exporter = new ExporterChangeableWrapper<T>((Exporter<T>)protocol.export(invokerDelegete), originInvoker); bounds.put(key, exporter); } } } return (ExporterChangeableWrapper<T>) exporter; }

3 December 2019, 02:14 | Views: 9663

Add new comment

For adding a comment, please log in
or create account

0 comments