Dubbo RPC middleware is an open source framework, the underlying data transmission used by default Netty, then theoretically handle the request is asynchronous, and why we use is synchronous it? Dubbo framework is certainly done a deal with asynchronous transfer synchronization.
First, we have to sort out at the asynchronous transfer synchronization, what our needs?
1, the caller then requests a remote service, you need to wait for the results, at the moment, it should block the request thread
2, the remote service returns the results, wake-up request thread, the caller get results
Dubbo synchronous asynchronous transfer, the core class is DefaultFuture, the core is get (), received (Channel channel, Response response).
DefaultFuture constructor:
. 1 Private static Final the Map <Long, Channel> = the CHANNELS new new of ConcurrentHashMap <Long, Channel> (); 2 . 3 // every request generates a DefaultFuture object, and then saved to FUTURES, the request return result, based on the id from FUTURES DefaultFuture find the corresponding object, and delete . 4 Private static Final the Map <Long, DefaultFuture> = FUTURES new new of ConcurrentHashMap <Long, DefaultFuture> (); . 5 . 6 // generated when AtomicLong incremented from 0, created Request object ID . 7 Private Final Long ID; . 8 Private Final Channel Channel; . 9 // request object 10 Private Final the Request Request; . 11 // timeouts 12 is Private Final int timeout; 13 is // used herein Lock and Condition implementation waiting notification mechanism 14 Private Final Lock Lock = new new of ReentrantLock (); 15 Private Final Condition DONE = lock.newCondition (); 16 Private Final Long Start = System.currentTimeMillis (); . 17 Private volatile Long Sent; 18 is // returns the results of the request . 19 Private volatile Response response; 20 private volatile ResponseCallback callback; 21 22 public DefaultFuture(Channel channel, Request request, int timeout) { 23 this.channel = channel; 24 this.request = request; 25 this.id = request.getId(); 26 this.timeout = timeout > 0 ? timeout : channel.getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT); 27 // put into waiting map. 28 FUTURES.put(id, this); 29 CHANNELS.put(id, channel); 30 }
get():
. 1 public Object GET ( int timeout) throws a RemotingException { 2 IF (timeout <= 0 ) { . 3 timeout = Constants.DEFAULT_TIMEOUT; . 4 } . 5 // isDone () method is to determine whether there is Response value (i.e., if there results returned) 6 IF (! {isDone ()) . 7 Long Start = System.currentTimeMillis (); . 8 Lock.lock (); . 9 the try { 10 the while (! isDone ()) { . 11 // out waiting 12 done.await (timeout, TimeUnit.MILLISECONDS); 13 is // if the results returned, or timed out, the loop exits 14 IF (isDone () || System.currentTimeMillis () - Start> timeout) { 15 BREAK ; 16 } . 17 } 18 is } the catch (InterruptedException E) { . 19 the throw new new a RuntimeException (E); 20 is } the finally { 21 is lock.unlock (); 22 is } 23 is // If the overtime, will throw an exception 24 IF(! IsDone ()) { 25 the throw new new a TimeoutException (Sent> 0, Channel, getTimeoutMessage ( to false )); 26 is } 27 } 28 // remote service returns normally result is returned to the caller 29 return returnFromResponse (); 30 }
received(Channel channel, Response response):
1 public static void received(Channel channel, Response response) { 2 try { 3 // 根据请求id从FUTURES中获取DefaultFuture,并删除 4 DefaultFuture future = FUTURES.remove(response.getId()); 5 if (future != null) { 6 future.doReceived(response); 7 } else { 8 logger.warn("The timeout response finally returned at " 9 + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())) 10 + ", response " + response 11 + (channel == null ? "" : ", channel: " + channel.getLocalAddress() 12 + " -> " + channel.getRemoteAddress())); 13 } 14 } finally { 15 // CHANNELS也删除 16 CHANNELS.remove(response.getId()); 17 } 18 }
1 private void doReceived(Response res) { 2 lock.lock(); 3 try { 4 response = res; 5 if (done != null) { 6 // 唤醒阻塞的线程 7 done.signal(); 8 } 9 } finally { 10 lock.unlock(); 11 } 12 if (callback != null) { 13 invokeCallback(callback); 14 } 15 }
Summary: The principle Dubbo asynchronous transfer synchronization, in fact, is the use of Lock and Condition achieve a wait notification mechanism. Request return result match, then the request is received and implemented by transfer id.