Search in sources :

Example 1 with Merger

use of org.apache.dubbo.rpc.cluster.Merger in project dubbo by alibaba.

the class MergeableClusterInvoker method doInvoke.

@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    checkInvokers(invokers, invocation);
    String merger = getUrl().getMethodParameter(invocation.getMethodName(), MERGER_KEY);
    if (ConfigUtils.isEmpty(merger)) {
        // If a method doesn't have a merger, only invoke one Group
        for (final Invoker<T> invoker : invokers) {
            if (invoker.isAvailable()) {
                try {
                    return invoker.invoke(invocation);
                } catch (RpcException e) {
                    if (e.isNoInvokerAvailableAfterFilter()) {
                        log.debug("No available provider for service" + getUrl().getServiceKey() + " on group " + invoker.getUrl().getParameter(GROUP_KEY) + ", will continue to try another group.");
                    } else {
                        throw e;
                    }
                }
            }
        }
        return invokers.iterator().next().invoke(invocation);
    }
    Class<?> returnType;
    try {
        returnType = getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes()).getReturnType();
    } catch (NoSuchMethodException e) {
        returnType = null;
    }
    Map<String, Result> results = new HashMap<>();
    for (final Invoker<T> invoker : invokers) {
        RpcInvocation subInvocation = new RpcInvocation(invocation, invoker);
        subInvocation.setAttachment(ASYNC_KEY, "true");
        results.put(invoker.getUrl().getServiceKey(), invoker.invoke(subInvocation));
    }
    Object result = null;
    List<Result> resultList = new ArrayList<Result>(results.size());
    for (Map.Entry<String, Result> entry : results.entrySet()) {
        Result asyncResult = entry.getValue();
        try {
            Result r = asyncResult.get();
            if (r.hasException()) {
                log.error("Invoke " + getGroupDescFromServiceKey(entry.getKey()) + " failed: " + r.getException().getMessage(), r.getException());
            } else {
                resultList.add(r);
            }
        } catch (Exception e) {
            throw new RpcException("Failed to invoke service " + entry.getKey() + ": " + e.getMessage(), e);
        }
    }
    if (resultList.isEmpty()) {
        return AsyncRpcResult.newDefaultAsyncResult(invocation);
    } else if (resultList.size() == 1) {
        return AsyncRpcResult.newDefaultAsyncResult(resultList.get(0).getValue(), invocation);
    }
    if (returnType == void.class) {
        return AsyncRpcResult.newDefaultAsyncResult(invocation);
    }
    if (merger.startsWith(".")) {
        merger = merger.substring(1);
        Method method;
        try {
            method = returnType.getMethod(merger, returnType);
        } catch (NoSuchMethodException e) {
            throw new RpcException("Can not merge result because missing method [ " + merger + " ] in class [ " + returnType.getName() + " ]");
        }
        ReflectUtils.makeAccessible(method);
        result = resultList.remove(0).getValue();
        try {
            if (method.getReturnType() != void.class && method.getReturnType().isAssignableFrom(result.getClass())) {
                for (Result r : resultList) {
                    result = method.invoke(result, r.getValue());
                }
            } else {
                for (Result r : resultList) {
                    method.invoke(result, r.getValue());
                }
            }
        } catch (Exception e) {
            throw new RpcException("Can not merge result: " + e.getMessage(), e);
        }
    } else {
        Merger resultMerger;
        if (ConfigUtils.isDefault(merger)) {
            resultMerger = MergerFactory.getMerger(returnType);
        } else {
            resultMerger = ExtensionLoader.getExtensionLoader(Merger.class).getExtension(merger);
        }
        if (resultMerger != null) {
            List<Object> rets = new ArrayList<Object>(resultList.size());
            for (Result r : resultList) {
                rets.add(r.getValue());
            }
            result = resultMerger.merge(rets.toArray((Object[]) Array.newInstance(returnType, 0)));
        } else {
            throw new RpcException("There is no merger to merge result.");
        }
    }
    return AsyncRpcResult.newDefaultAsyncResult(result, invocation);
}
Also used : RpcInvocation(org.apache.dubbo.rpc.RpcInvocation) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) RpcException(org.apache.dubbo.rpc.RpcException) AsyncRpcResult(org.apache.dubbo.rpc.AsyncRpcResult) Result(org.apache.dubbo.rpc.Result) Merger(org.apache.dubbo.rpc.cluster.Merger) RpcException(org.apache.dubbo.rpc.RpcException) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with Merger

use of org.apache.dubbo.rpc.cluster.Merger in project dubbo by alibaba.

the class MergerFactory method getMerger.

/**
 * Find the merger according to the returnType class, the merger will
 * merge an array of returnType into one
 *
 * @param returnType the merger will return this type
 * @return the merger which merges an array of returnType into one, return null if not exist
 * @throws IllegalArgumentException if returnType is null
 */
public static <T> Merger<T> getMerger(Class<T> returnType) {
    if (returnType == null) {
        throw new IllegalArgumentException("returnType is null");
    }
    Merger result;
    if (returnType.isArray()) {
        Class type = returnType.getComponentType();
        result = MERGER_CACHE.get(type);
        if (result == null) {
            loadMergers();
            result = MERGER_CACHE.get(type);
        }
        if (result == null && !type.isPrimitive()) {
            result = ArrayMerger.INSTANCE;
        }
    } else {
        result = MERGER_CACHE.get(returnType);
        if (result == null) {
            loadMergers();
            result = MERGER_CACHE.get(returnType);
        }
    }
    return result;
}
Also used : Merger(org.apache.dubbo.rpc.cluster.Merger)

Example 3 with Merger

use of org.apache.dubbo.rpc.cluster.Merger in project dubbo by alibaba.

the class MergerFactory method loadMergers.

static void loadMergers() {
    Set<String> names = ExtensionLoader.getExtensionLoader(Merger.class).getSupportedExtensions();
    for (String name : names) {
        Merger m = ExtensionLoader.getExtensionLoader(Merger.class).getExtension(name);
        MERGER_CACHE.putIfAbsent(ReflectUtils.getGenericClass(m.getClass()), m);
    }
}
Also used : Merger(org.apache.dubbo.rpc.cluster.Merger)

Aggregations

Merger (org.apache.dubbo.rpc.cluster.Merger)3 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 AsyncRpcResult (org.apache.dubbo.rpc.AsyncRpcResult)1 Result (org.apache.dubbo.rpc.Result)1 RpcException (org.apache.dubbo.rpc.RpcException)1 RpcInvocation (org.apache.dubbo.rpc.RpcInvocation)1