Dubbo的远程回调

在Dubbo作为消费者再通过NettyServer准备调用相应服务的发送请求的时候先通过NettyCodeAdapter来对具体的数据进行编码。

在编码的过程中,遍历方法中的参数,来判断如果消费者调用了相应参数的方法,是否有必要进行远程回调。

判断的依据为,在消费者组装需要远程调用的方法的参数的时候,对所需要回调的方法中的第几个参数进行了配置,生产者根据其方法的第几个参数的callBack属性来判断是否有必要进行回调,该参数在url中的形式为methodName.第几个参数.callBack。

private static byte isCallBack(URL url, String methodName, int argIndex) {
    // parameter callback rule: method-name.parameter-index(starting from 0).callback
    byte isCallback = CALLBACK_NONE;
    if (url != null) {
        String callback = url.getParameter(methodName + "." + argIndex + ".callback");
        if (callback != null) {
            if (callback.equalsIgnoreCase("true")) {
                isCallback = CALLBACK_CREATE;
            } else if (callback.equalsIgnoreCase("false")) {
                isCallback = CALLBACK_DESTROY;
            }
        }
    }
    return isCallback;
}

根据这个参数来确认是否有必要进行回调。

在判断生产者需要对相应的参数的调用进行远程回调的时候,则需要跟生产者一样暴露相应的回调方法。

private static String exportOrunexportCallbackService(Channel channel, URL url, Class clazz, Object inst, Boolean export) throws IOException {
    int instid = System.identityHashCode(inst);

    Map<String, String> params = new HashMap<String, String>(3);
    // no need to new client again
    params.put(Constants.IS_SERVER_KEY, Boolean.FALSE.toString());
    // mark it's a callback, for troubleshooting
    params.put(Constants.IS_CALLBACK_SERVICE, Boolean.TRUE.toString());
    String group = url.getParameter(Constants.GROUP_KEY);
    if (group != null && group.length() > 0) {
        params.put(Constants.GROUP_KEY, group);
    }
    // add method, for verifying against method, automatic fallback (see dubbo protocol)
    params.put(Constants.METHODS_KEY, StringUtils.join(Wrapper.getWrapper(clazz).getDeclaredMethodNames(), ","));

    Map<String, String> tmpmap = new HashMap<String, String>(url.getParameters());
    tmpmap.putAll(params);
    tmpmap.remove(Constants.VERSION_KEY);// doesn't need to distinguish version for callback
    tmpmap.put(Constants.INTERFACE_KEY, clazz.getName());
    URL exporturl = new URL(DubboProtocol.NAME, channel.getLocalAddress().getAddress().getHostAddress(), channel.getLocalAddress().getPort(), clazz.getName() + "." + instid, tmpmap);

    // no need to generate multiple exporters for different channel in the same JVM, cache key cannot collide.
    String cacheKey = getClientSideCallbackServiceCacheKey(instid);
    String countkey = getClientSideCountKey(clazz.getName());
    if (export) {
        // one channel can have multiple callback instances, no need to re-export for different instance.
        if (!channel.hasAttribute(cacheKey)) {
            if (!isInstancesOverLimit(channel, url, clazz.getName(), instid, false)) {
                Invoker<?> invoker = proxyFactory.getInvoker(inst, clazz, exporturl);
                // should destroy resource?
                Exporter<?> exporter = protocol.export(invoker);
                // this is used for tracing if instid has published service or not.
                channel.setAttribute(cacheKey, exporter);
                logger.info("export a callback service :" + exporturl + ", on " + channel + ", url is: " + url);
                increaseInstanceCount(channel, countkey);
            }
        }
    } else {
        if (channel.hasAttribute(cacheKey)) {
            Exporter<?> exporter = (Exporter<?>) channel.getAttribute(cacheKey);
            exporter.unexport();
            channel.removeAttribute(cacheKey);
            decreaseInstanceCount(channel, countkey);
        }
    }
    return String.valueOf(instid);
}

这里根据消费者的地址,直接构造了直连的url来完成远程回调的需要。之后与别的服务一样构造代理,并通过DubboProtocol的export()方法进行暴露。并将得到的exporter作为value,这样并通过参数的hashcode构造key,组成键值对存储在channel中,保证生产者能够接收到请求后根据key在channel中得到相应的exporter,完成代理的创建,使得可以完成远程回调的功能。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值