Dubbo异步转同步

  Dubbo是一款开源RPC框架,底层使用Netty作为默认的数据传输方式,那么请求处理理论上是异步的,但是我们在使用Dubbo时,是同步拿到结果的,这是因为Dubbo框架帮我们做了异步转同步的操作。

​ 构造一个DefaultFuture,并将DefaultFuture放在Map中,key为请求是生成的唯一id。

private static final Map<Long, Channel> CHANNELS = new ConcurrentHashMap<>();
    // 每次请求都会生成一个DefaultFuture对象,然后保存到FUTURES中,
    // 请求返回结果时,根据id从FUTURES中找到对应的DefaultFuture对象,并删除
    private static final Map<Long, DefaultFuture> FUTURES = new ConcurrentHashMap<>();

    public static final Timer TIME_OUT_TIMER = new HashedWheelTimer(
            new NamedThreadFactory("dubbo-future-timeout", true),
            30,
            TimeUnit.MILLISECONDS);

    // invoke id.
    private final Long id;
    private final Channel channel;
    // 请求对象
    private final Request request;
    // 超时时间
    private final int timeout;
    private final long start = System.currentTimeMillis();
    private volatile long sent;
    private Timeout timeoutCheckTask;

    private DefaultFuture(Channel channel, Request request, int timeout) {
        this.channel = channel;
        this.request = request;
        this.id = request.getId();
        this.timeout = timeout > 0 ? timeout : channel.getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT);
        // put into waiting map.
        FUTURES.put(id, this);
        CHANNELS.put(id, channel);
    }

​ 获取结果,如果结果未返回就休眠等待。

public Object get(int timeout) throws RemotingException {
          if (timeout <= 0) {
              timeout = Constants.DEFAULT_TIMEOUT;
          }
          // isDone()方法就是判断Response是否有值(即是否有返回结果)
          if (!isDone()) {
              long start = System.currentTimeMillis();
              lock.lock();
              try {
                 while (!isDone()) {
                     // 超时等待
                     done.await(timeout, TimeUnit.MILLISECONDS);
                     // 如果有返回结果了,或者,超时了,就退出循环
                     if (isDone() || System.currentTimeMillis() - start > timeout) {
                         break;
                     }
                 }
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             } finally {
                 lock.unlock();
             }
             // 如果是超时了,就抛出异常
             if (!isDone()) {
                 throw new TimeoutException(sent > 0, channel, getTimeoutMessage(false));
             }
         }
         // 远程服务正常返回结果,则返回给调用方
         return returnFromResponse();
     }

​ 服务提供者处理完成将结果写回,并唤醒消费者。

public static void received(Channel channel, Response response) {
        try {
            // 根据请求id从FUTURES中获取DefaultFuture,并删除
            DefaultFuture future = FUTURES.remove(response.getId());
            if (future != null) {
                future.doReceived(response);
            } else {
                logger.warn("The timeout response finally returned at "
                        + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()))
                        + ", response " + response
                        + (channel == null ? "" : ", channel: " + channel.getLocalAddress()
                        + " -> " + channel.getRemoteAddress()));
            }
        } finally {
            // CHANNELS也删除
            CHANNELS.remove(response.getId());
        }
    }
private void doReceived(Response res) {
        lock.lock();
        try {
            response = res;
            if (done != null) {
                // 唤醒阻塞的线程
                done.signal();
            }
        } finally {
            lock.unlock();
        }
        if (callback != null) {
            invokeCallback(callback);
        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值