Example #1
0
 void retryFailed(IClientPool pool)
 {
     if (failed.Count == 0)
     {
         return;
     }
     foreach (var entry in failed)
     {
         IInvocation invocation = entry.Key;
         var         client     = pool.GetClient(entry.Value);
         try
         {
             var refer  = client.Refer();
             var result = refer.Invoke(invocation);
             pool.Recovery(client);
             URL cluster;
             failed.TryRemove(invocation, out cluster);
         }
         catch (Exception e)
         {
             pool.Recovery(client);
             logger.Error("Failed retry to invoke method " + invocation.MethodInfo.Name + ", waiting again.", e);
         }
     }
 }
Example #2
0
        public override IClusterResult DoInvoke(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var       goodUrls  = new List <URL>();
            var       badUrls   = new List <BadUrl>();
            IResult   result    = null;
            Exception exception = null;
            var       isThrow   = false;

            checkInvokers(urls, invocation);
            var invoker = base.select(loadbalance, invocation, urls, null);

            try
            {
                var client = pool.GetClient(invoker);
                try
                {
                    var refer = client.Refer();
                    result = refer.Invoke(invocation);
                    pool.Recovery(client);
                    goodUrls.Add(invoker);
                }
                catch (Exception ex)
                {
                    pool.Recovery(client);
                    throw ex;
                }
            }
            catch (Exception e)
            {
                isThrow = true;

                if (e is RpcException && ((RpcException)e).Biz)
                { // biz exception.
                    exception = e;
                    //throw (RpcException)e;
                }
                else
                {
                    exception = new RpcException(e is RpcException ? ((RpcException)e).Code : 0, "Failfast invoke providers "
                                                 + invoker + " " + loadbalance.GetType().Name
                                                 + " select from all providers " + string.Join(",", urls)
                                                 + " for service " + invocation.TargetType.FullName
                                                 + " method " + invocation.MethodInfo.Name
                                                 //+ " on consumer " + NetUtils.getLocalHost()
                                                 //+ " use zooyard version " + Version.getVersion()
                                                 + ", but no luck to perform the invocation. Last error is: " + e.Message, e.InnerException != null ? e.InnerException : e);
                }

                badUrls.Add(new BadUrl {
                    Url = invoker, BadTime = DateTime.Now, CurrentException = exception
                });
            }

            return(new ClusterResult(result, goodUrls, badUrls, exception, isThrow));
        }
Example #3
0
        async Task RetryFailed <T>(IClientPool pool)
        {
            if (failed.Count == 0)
            {
                return;
            }
            foreach (var entry in failed)
            {
                IInvocation invocation = entry.Key;
                var         client     = await pool.GetClient(entry.Value);

                try
                {
                    var refer = await client.Refer();

                    _source.WriteConsumerBefore(refer.Instance, entry.Value, invocation);
                    var result = await refer.Invoke <T>(invocation);

                    _source.WriteConsumerAfter(entry.Value, invocation, result);
                    await pool.Recovery(client);

                    failed.TryRemove(invocation, out URL cluster);
                }
                catch (Exception e)
                {
                    _source.WriteConsumerError(entry.Value, invocation, e);
                    await pool.DestoryClient(client);

                    Logger().LogError(e, $"Failed retry to invoke method {invocation.MethodInfo.Name}, waiting again.");
                }
            }
        }
Example #4
0
        public override IClusterResult DoInvoke(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            checkInvokers(urls, invocation);
            RpcContext.GetContext().SetInvokers(urls);
            Exception exception = null;
            var       goodUrls  = new List <URL>();
            var       badUrls   = new List <BadUrl>();
            var       isThrow   = false;
            IResult   result    = null;

            foreach (var invoker in urls)
            {
                try
                {
                    var client = pool.GetClient(invoker);
                    try
                    {
                        var refer = client.Refer();
                        result = refer.Invoke(invocation);
                        pool.Recovery(client);
                        goodUrls.Add(invoker);
                    }
                    catch (Exception ex)
                    {
                        pool.Recovery(client);
                        throw ex;
                    }
                }
                catch (Exception e)
                {
                    exception = e;
                    badUrls.Add(new BadUrl {
                        Url = invoker, BadTime = DateTime.Now, CurrentException = exception
                    });
                    logger.Warn(e.Message, e);
                }
            }
            if (exception != null)
            {
                isThrow = true;
            }
            var clusterResult = new ClusterResult(result, goodUrls, badUrls, exception, isThrow);

            return(clusterResult);
        }
Example #5
0
        public override async Task <IClusterResult <T> > DoInvoke <T>(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var       goodUrls  = new List <URL>();
            var       badUrls   = new List <BadUrl>();
            Exception exception = null;

            checkInvokers(urls, invocation, address);
            var invoker = base.select(loadbalance, invocation, urls, null);

            IResult <T> result;
            var         watch = Stopwatch.StartNew();

            try
            {
                var client = await pool.GetClient(invoker);

                try
                {
                    var refer = await client.Refer();

                    _source.WriteConsumerBefore(refer.Instance, invoker, invocation);
                    result = await refer.Invoke <T>(invocation);

                    _source.WriteConsumerAfter(invoker, invocation, result);
                    await pool.Recovery(client);

                    goodUrls.Add(invoker);
                }
                catch (Exception ex)
                {
                    await pool.DestoryClient(client).ConfigureAwait(false);

                    _source.WriteConsumerError(invoker, invocation, ex);
                    throw ex;
                }
            }
            catch (Exception e)
            {
                Logger().LogError(e, $"Failback to invoke method {invocation.MethodInfo.Name}, wait for retry in background. Ignored exception:{e.Message}");
                AddFailed <T>(pool, invocation, invoker);
                watch.Stop();
                result    = new RpcResult <T>(watch.ElapsedMilliseconds); // ignore
                exception = e;
                badUrls.Add(new BadUrl {
                    Url = invoker, BadTime = DateTime.Now, CurrentException = exception
                });
            }
            finally
            {
                if (watch.IsRunning)
                {
                    watch.Stop();
                }
            }

            return(new ClusterResult <T>(result, goodUrls, badUrls, exception, false));
        }
Example #6
0
        public override async Task <IClusterResult <T> > DoInvoke <T>(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            checkInvokers(urls, invocation, address);
            RpcContext.GetContext().SetInvokers(urls);
            Exception   exception = null;
            var         goodUrls  = new List <URL>();
            var         badUrls   = new List <BadUrl>();
            var         isThrow   = false;
            IResult <T> result    = null;

            foreach (var invoker in urls)
            {
                try
                {
                    var client = await pool.GetClient(invoker);

                    try
                    {
                        var refer = await client.Refer();

                        _source.WriteConsumerBefore(refer.Instance, invoker, invocation);
                        result = await refer.Invoke <T>(invocation);

                        _source.WriteConsumerAfter(invoker, invocation, result);
                        await pool.Recovery(client);

                        goodUrls.Add(invoker);
                    }
                    catch (Exception ex)
                    {
                        await pool.DestoryClient(client);

                        _source.WriteConsumerError(invoker, invocation, ex);
                        throw ex;
                    }
                }
                catch (Exception e)
                {
                    exception = e;
                    badUrls.Add(new BadUrl {
                        Url = invoker, BadTime = DateTime.Now, CurrentException = exception
                    });
                    Logger().LogWarning(e, e.Message);
                }
            }
            if (exception != null)
            {
                isThrow = true;
            }
            var clusterResult = new ClusterResult <T>(result, goodUrls, badUrls, exception, isThrow);

            return(clusterResult);
        }
Example #7
0
        public override IClusterResult DoInvoke(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var       goodUrls  = new List <URL>();
            var       badUrls   = new List <BadUrl>();
            IResult   result    = null;
            Exception exception = null;

            checkInvokers(urls, invocation);
            var invoker = base.select(loadbalance, invocation, urls, null);

            try
            {
                var client = pool.GetClient(invoker);
                try
                {
                    var refer = client.Refer();
                    result = refer.Invoke(invocation);
                    pool.Recovery(client);
                    goodUrls.Add(invoker);
                }
                catch (Exception ex)
                {
                    pool.Recovery(client);
                    throw ex;
                }
            }
            catch (Exception e)
            {
                logger.Error("Failback to invoke method " + invocation.MethodInfo.Name + ", wait for retry in background. Ignored exception: " + e.Message + ", ", e);
                addFailed(pool, invocation, invoker);
                result    = new RpcResult(); // ignore
                exception = e;
                badUrls.Add(new BadUrl {
                    Url = invoker, BadTime = DateTime.Now, CurrentException = exception
                });
            }

            return(new ClusterResult(result, goodUrls, badUrls, exception, false));
        }
Example #8
0
        public override IClusterResult DoInvoke(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            IResult   result    = null;
            var       goodUrls  = new List <URL>();
            var       badUrls   = new List <BadUrl>();
            Exception exception = null;

            checkInvokers(urls, invocation);
            var invoker = base.select(loadbalance, invocation, urls, null);

            try
            {
                var client = pool.GetClient(invoker);
                try
                {
                    var refer = client.Refer();
                    result = refer.Invoke(invocation);
                    pool.Recovery(client);
                    goodUrls.Add(invoker);
                    return(new ClusterResult(result, goodUrls, badUrls, exception, false));
                }
                catch (Exception ex)
                {
                    pool.Recovery(client);
                    throw ex;
                }
            }
            catch (Exception e)
            {
                exception = e;
                badUrls.Add(new BadUrl {
                    Url = invoker, BadTime = DateTime.Now, CurrentException = exception
                });
                logger.Error("Failsafe ignore exception: " + e.Message, e);
                result = new RpcResult(e); // ignore
            }
            return(new ClusterResult(result, goodUrls, badUrls, exception, false));
        }
Example #9
0
        public override async Task <IClusterResult <T> > DoInvoke <T>(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var       goodUrls  = new List <URL>();
            var       badUrls   = new List <BadUrl>();
            Exception exception = null;

            checkInvokers(urls, invocation, address);
            var         invoker = base.select(loadbalance, invocation, urls, null);
            IResult <T> result;

            try
            {
                var client = await pool.GetClient(invoker);

                try
                {
                    var refer = await client.Refer();

                    _source.WriteConsumerBefore(refer.Instance, invoker, invocation);
                    result = await refer.Invoke <T>(invocation);

                    _source.WriteConsumerAfter(invoker, invocation, result);
                    await pool.Recovery(client);

                    goodUrls.Add(invoker);
                    return(new ClusterResult <T>(result, goodUrls, badUrls, exception, false));
                }
                catch (Exception ex)
                {
                    await pool.DestoryClient(client).ConfigureAwait(false);

                    _source.WriteConsumerError(invoker, invocation, ex);
                    throw ex;
                }
            }
            catch (Exception e)
            {
                exception = e;
                badUrls.Add(new BadUrl {
                    Url = invoker, BadTime = DateTime.Now, CurrentException = exception
                });
                Logger().LogError(e, $"Failsafe ignore exception: {e.Message}");
                result = new RpcResult <T>(e); // ignore
            }
            return(new ClusterResult <T>(result, goodUrls, badUrls, exception, false));
        }
Example #10
0
        public override async Task <IClusterResult <T> > DoInvoke <T>(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var         goodUrls  = new List <URL>();
            var         badUrls   = new List <BadUrl>();
            IResult <T> result    = null;
            Exception   exception = null;
            var         isThrow   = false;

            checkInvokers(urls, invocation, address);
            var invoker = base.select(loadbalance, invocation, urls, null);

            try
            {
                var client = await pool.GetClient(invoker);

                try
                {
                    var refer = await client.Refer();

                    _source.WriteConsumerBefore(refer.Instance, invoker, invocation);
                    result = await refer.Invoke <T>(invocation);

                    _source.WriteConsumerAfter(invoker, invocation, result);
                    await pool.Recovery(client);

                    goodUrls.Add(invoker);
                }
                catch (Exception ex)
                {
                    await pool.DestoryClient(client);

                    _source.WriteConsumerError(invoker, invocation, ex);
                    throw ex;
                }
            }
            catch (Exception e)
            {
                isThrow = true;

                if (e is RpcException eBiz && eBiz.Biz)
                {
                    // biz exception.
                    exception = e;
                    //throw (RpcException)e;
                }
Example #11
0
        public override IClusterResult DoInvoke(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var goodUrls = new List <URL>();
            var badUrls  = new List <BadUrl>();
            var invokers = urls;

            string merger = address.GetMethodParameter(invocation.MethodInfo.Name, MERGER_KEY);

            if (string.IsNullOrEmpty(merger))
            {
                // If a method doesn't have a merger, only invoke one Group
                foreach (var invoker in invokers)
                {
                    try
                    {
                        var client = pool.GetClient(invoker);
                        try
                        {
                            var refer        = client.Refer();
                            var invokeResult = refer.Invoke(invocation);
                            pool.Recovery(client);
                            goodUrls.Add(invoker);
                            return(new ClusterResult(invokeResult, goodUrls, badUrls, null, false));
                        }
                        catch (Exception ex)
                        {
                            pool.Recovery(client);
                            throw ex;
                        }
                    }
                    catch (Exception e)
                    {
                        badUrls.Add(new BadUrl {
                            Url = invoker, BadTime = DateTime.Now, CurrentException = e
                        });
                        return(new ClusterResult(new RpcResult(e), goodUrls, badUrls, e, true));
                    }
                }

                try
                {
                    var client2 = pool.GetClient(invokers[0]);
                    try
                    {
                        var refer2  = client2.Refer();
                        var result2 = refer2.Invoke(invocation);
                        pool.Recovery(client2);
                        goodUrls.Add(invokers[0]);
                        return(new ClusterResult(result2, goodUrls, badUrls, null, false));
                    }
                    catch (Exception ex)
                    {
                        client2.Dispose();
                        throw ex;
                    }
                }
                catch (Exception e)
                {
                    badUrls.Add(new BadUrl {
                        Url = invokers[0], BadTime = DateTime.Now, CurrentException = e
                    });
                    return(new ClusterResult(new RpcResult(e), goodUrls, badUrls, e, true));
                }
            }

            Type returnType;

            try
            {
                returnType = invocation.TargetType.GetMethod(invocation.MethodInfo.Name, invocation.ArgumentTypes).ReturnType;
            }
            catch (Exception)
            {
                returnType = null;
            }

            IDictionary <string, Task <IResult> > results = new Dictionary <string, Task <IResult> >();

            foreach (var invoker in invokers)
            {
                var task = Task.Run <IResult>(() =>
                {
                    try
                    {
                        var client = pool.GetClient(invoker);
                        try
                        {
                            var refer        = client.Refer();
                            var invoceResult = refer.Invoke(invocation);
                            pool.Recovery(client);
                            goodUrls.Add(invoker);
                            return(invoceResult);
                        }
                        catch (Exception ex)
                        {
                            pool.Recovery(client);
                            throw ex;
                        }
                    }
                    catch (Exception e)
                    {
                        badUrls.Add(new BadUrl {
                            Url = invoker, BadTime = DateTime.Now, CurrentException = e
                        });
                        return(new RpcResult(e));
                    }
                });
                results.Add(invoker.ServiceKey, task);
            }

            object resultValue = null;

            var resultList = new List <IResult>(results.Count);

            int timeout = address.GetMethodParameter(invocation.MethodInfo.Name, TIMEOUT_KEY, DEFAULT_TIMEOUT);

            Task.WaitAll(results.Values.ToArray(), timeout);
            foreach (var entry in results)
            {
                try
                {
                    //IResult r = future.GetAwaiter().GetResult();// (timeout, TimeUnit.MILLISECONDS);
                    var r = entry.Value.Result;
                    if (r.HasException)
                    {
                        logger.Error($"Invoke {entry.Key} {getGroupDescFromServiceKey(entry.Key)}  failed: {r.Exception.Message}", r.Exception);
                    }
                    else
                    {
                        resultList.Add(r);
                    }
                }
                catch (Exception e)
                {
                    var ex = new RpcException($"Failed to invoke service {entry.Key}: {e.Message}", e);
                    return(new ClusterResult(new RpcResult(ex), goodUrls, badUrls, ex, true));
                }
            }

            if (resultList.Count == 0)
            {
                return(new ClusterResult(new RpcResult(), goodUrls, badUrls, null, false));
            }
            else if (resultList.Count == 1)
            {
                return(new ClusterResult(resultList[0], goodUrls, badUrls, null, false));
            }

            if (returnType == typeof(void))
            {
                return(new ClusterResult(new RpcResult(), goodUrls, badUrls, null, false));
            }

            if (merger.StartsWith("."))
            {
                merger = merger.Substring(1);
                MethodInfo method;
                try
                {
                    method = returnType.GetMethod(merger, new[] { returnType });
                }
                catch (Exception e)
                {
                    var ex = new RpcException($"Can not merge result because missing method [{merger}] in class [{returnType.Name}]{e.Message}", e);
                    return(new ClusterResult(new RpcResult(ex), goodUrls, badUrls, ex, true));
                }

                if (method == null)
                {
                    var ex = new RpcException($"Can not merge result because missing method [ {merger} ] in class [ {returnType.Name} ]");
                    return(new ClusterResult(new RpcResult(ex), goodUrls, badUrls, ex, true));
                }

                //if (!method.IsPublic)
                //{
                //method.setAccessible(true);
                //}
                resultValue = resultList[0].Value;
                resultList.RemoveAt(0);
                try
                {
                    if (method.ReturnType != typeof(void) &&
                        method.ReturnType.IsAssignableFrom(resultValue.GetType()))
                    {
                        foreach (var r in resultList)
                        {
                            resultValue = method.Invoke(resultValue, new[] { r.Value });
                        }
                    }
                    else
                    {
                        foreach (var r in resultList)
                        {
                            method.Invoke(resultValue, new[] { r.Value });
                        }
                    }
                }
                catch (Exception e)
                {
                    var ex = new RpcException($"Can not merge result: {e.Message}", e);
                    return(new ClusterResult(new RpcResult(ex), goodUrls, badUrls, ex, true));
                }
            }
            else
            {
                IMerger resultMerger;
                if (merger.ToLower() == "true" || merger.ToLower() == "default")
                {
                    //resultMerger = DefaultMergers[returnType];
                    resultMerger = MergerFactory.GetMerger(returnType, DefaultMergers);
                }
                else
                {
                    resultMerger = MySelfMergers[merger];
                    //resultMerger = ExtensionLoader.getExtensionLoader(Merger.class).getExtension(merger);
                }

                if (resultMerger != null)
                {
                    var rets = new List <object>(resultList.Count);
                    foreach (var r in resultList)
                    {
                        rets.Add(r.Value);
                    }
                    resultValue = resultMerger.GetType().GetMethod("Merge", new Type[] { returnType }).Invoke(resultMerger, new[] { rets });
                }
                else
                {
                    var ex = new RpcException("There is no merger to merge result.");
                    return(new ClusterResult(new RpcResult(ex), goodUrls, badUrls, ex, true));
                }
            }
            return(new ClusterResult(new RpcResult(resultValue), goodUrls, badUrls, null, false));
        }
Example #12
0
        public override IClusterResult DoInvoke(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var goodUrls = new List <URL>();
            var badUrls  = new List <BadUrl>();
            //IResult result = null;

            var copyinvokers = urls;

            checkInvokers(copyinvokers, invocation);

            //*getUrl();
            int len = address.GetMethodParameter(invocation.MethodInfo.Name, RETRIES_KEY, DEFAULT_RETRIES) + 1;

            if (len <= 0)
            {
                len = 1;
            }
            // retry loop.
            RpcException  le        = null;                               // last exception.
            var           invoked   = new List <URL>(copyinvokers.Count); // invoked invokers.
            ISet <string> providers = new HashSet <string>();             //*len

            for (int i = 0; i < len; i++)
            {
                //重试时,进行重新选择,避免重试时invoker列表已发生变化.
                //注意:如果列表发生了变化,那么invoked判断会失效,因为invoker示例已经改变
                if (i > 0)
                {
                    //*checkWhetherDestroyed();
                    //*copyinvokers = list(invocation);
                    //重新检查一下
                    checkInvokers(copyinvokers, invocation);
                }
                var invoker = base.select(loadbalance, invocation, copyinvokers, invoked);
                invoked.Add(invoker);
                RpcContext.GetContext().SetInvokers(invoked);
                try
                {
                    var client = pool.GetClient(invoker);
                    try
                    {
                        var refer  = client.Refer();
                        var result = refer.Invoke(invocation);
                        pool.Recovery(client);
                        if (le != null && logger.IsWarnEnabled)
                        {
                            logger.Warn("Although retry the method " + invocation.MethodInfo.Name
                                        + " in the service " + invocation.TargetType.FullName
                                        + " was successful by the provider " + invoker.Address
                                        + ", but there have been failed providers " + string.Join(",", providers)
                                        + " (" + providers.Count + "/" + copyinvokers.Count
                                        + ") from the registry " + address.Address
                                        //+ " on the consumer " + NetUtils.GetLocalHost()
                                        //+ " using the dubbo version " + Version.getVersion() + ". Last error is: "
                                        + le.Message, le);
                        }
                        goodUrls.Add(invoker);
                        return(new ClusterResult(result, goodUrls, badUrls, le, false));
                    }
                    catch (Exception ex)
                    {
                        pool.Recovery(client);
                        throw ex;
                    }
                    //}
                    //catch (RpcException e)
                    //{
                    //    if (e.Biz)
                    //    { // biz exception.
                    //        throw e;
                    //    }
                    //    le = e;
                }
                catch (Exception e)
                {
                    le = new RpcException(e.Message, e);

                    var badUrl = badUrls.FirstOrDefault(w => w.Url == invoker);
                    if (badUrl != null)
                    {
                        badUrls.Remove(badUrl);
                    }
                    badUrls.Add(new BadUrl {
                        Url = invoker, BadTime = DateTime.Now, CurrentException = le
                    });
                }
                finally
                {
                    providers.Add(invoker.Address);
                }
            }

            var re = new RpcException(le != null ? le.Code : 0, "Failed to invoke the method "
                                      + invocation.MethodInfo.Name + " in the service " + invocation.TargetType.FullName
                                      + ". Tried " + len + " times of the providers " + string.Join(",", providers)
                                      + " (" + providers.Count + "/" + copyinvokers.Count
                                      //+ ") from the registry " + directory.getUrl().getAddress()
                                      //+ " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
                                      //+ Version.getVersion() + ". Last error is: "
                                      + (le != null ? le.Message : ""), le != null && le.InnerException != null ? le.InnerException : le);

            return(new ClusterResult(new RpcResult(re), goodUrls, badUrls, re, true));
        }
Example #13
0
        public override async Task <IClusterResult <T> > DoInvoke <T>(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            //IResult result = null;
            var goodUrls = new List <URL>();
            var badUrls  = new List <BadUrl>();

            checkInvokers(urls, invocation, address);
            IList <URL> selected;

            int forks   = address.GetParameter(FORKS_KEY, DEFAULT_FORKS);
            int timeout = address.GetParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT);

            if (forks <= 0 || forks >= urls.Count)
            {
                selected = urls;
            }
            else
            {
                selected = new List <URL>();
                for (int i = 0; i < forks; i++)
                {
                    //在invoker列表(排除selected)后,如果没有选够,则存在重复循环问题.见select实现.
                    var invoker = base.select(loadbalance, invocation, urls, selected);
                    if (!selected.Contains(invoker))
                    {//防止重复添加invoker
                        selected.Add(invoker);
                    }
                }
            }
            RpcContext.GetContext().SetInvokers(selected);
            var count = new AtomicInteger();

            var taskList = new Task <IResult <T> > [selected.Count];
            var index    = 0;

            foreach (var invoker in selected)
            {
                var task = Task.Run(async() => {
                    try
                    {
                        var client = await pool.GetClient(invoker);
                        try
                        {
                            var refer = await client.Refer();
                            _source.WriteConsumerBefore(refer.Instance, invoker, invocation);
                            var resultInner = await refer.Invoke <T>(invocation);
                            _source.WriteConsumerAfter(invoker, invocation, resultInner);
                            await pool.Recovery(client);
                            goodUrls.Add(invoker);
                            return(resultInner);
                        }
                        catch (Exception ex)
                        {
                            await pool.DestoryClient(client).ConfigureAwait(false);
                            _source.WriteConsumerError(invoker, invocation, ex);
                            throw ex;
                        }
                    }
                    catch (Exception e)
                    {
                        badUrls.Add(new BadUrl {
                            Url = invoker, BadTime = DateTime.Now, CurrentException = e
                        });
                        int value = count.IncrementAndGet();
                        if (value >= selected.Count)
                        {
                            return(new RpcResult <T>(e));
                        }
                    }
                    return(null);
                });
                taskList[index++] = task;
            }
            try
            {
                var retIndex = Task.WaitAny(taskList, timeout);
                var ret      = await taskList[retIndex];
                if (ret.HasException)
                {
                    Exception e = ret.Exception;
                    throw new RpcException(e is RpcException exception ? exception.Code : 0, "Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.Message, e.InnerException != null ? e.InnerException : e);
                }
                return(new ClusterResult <T>(ret, goodUrls, badUrls, null, false));
            }
            catch (Exception e)
            {
                var exception = new RpcException("Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.Message, e);
                return(new ClusterResult <T>(new RpcResult <T>(exception), goodUrls, badUrls, exception, true));
            }
        }
Example #14
0
        public override async Task <IClusterResult <T> > DoInvoke <T>(IClientPool pool, ILoadBalance loadbalance, URL address, IList <URL> urls, IInvocation invocation)
        {
            var goodUrls = new List <URL>();
            var badUrls  = new List <BadUrl>();
            var invokers = urls;

            var merger = address.GetMethodParameter(invocation.MethodInfo.Name, MERGER_KEY);

            // If a method doesn't have a merger, only invoke one Group
            if (string.IsNullOrEmpty(merger))
            {
                foreach (var invoker in invokers)
                {
                    try
                    {
                        var client = await pool.GetClient(invoker);

                        try
                        {
                            var refer = await client.Refer();

                            _source.WriteConsumerBefore(refer.Instance, invoker, invocation);
                            var invokeResult = await refer.Invoke <T>(invocation);

                            _source.WriteConsumerAfter(invoker, invocation, invokeResult);
                            await pool.Recovery(client);

                            goodUrls.Add(invoker);
                            return(new ClusterResult <T>(invokeResult, goodUrls, badUrls, null, false));
                        }
                        catch (Exception ex)
                        {
                            _source.WriteConsumerError(invoker, invocation, ex);
                            await pool.DestoryClient(client).ConfigureAwait(false);

                            throw ex;
                        }
                    }
                    catch (Exception e)
                    {
                        badUrls.Add(new BadUrl {
                            Url = invoker, BadTime = DateTime.Now, CurrentException = e
                        });
                        return(new ClusterResult <T>(new RpcResult <T>(e), goodUrls, badUrls, e, true));
                    }
                }

                var exMerger = new Exception($"merger: {merger} is null and the invokers is empty");
                return(new ClusterResult <T>(new RpcResult <T>(exMerger), goodUrls, badUrls, exMerger, true));
            }

            Type returnType = invocation.TargetType.GetMethod(invocation.MethodInfo.Name, invocation.ArgumentTypes).ReturnType;

            object resultValue = null;
            var    watch       = Stopwatch.StartNew();

            try
            {
                var results = new Dictionary <string, Task <IResult <T> > >();
                foreach (var invoker in invokers)
                {
                    var task = Task.Run(async() =>
                    {
                        try
                        {
                            var client = await pool.GetClient(invoker);
                            try
                            {
                                var refer = await client.Refer();
                                _source.WriteConsumerBefore(refer.Instance, invoker, invocation);
                                var invokeResult = await refer.Invoke <T>(invocation);
                                _source.WriteConsumerAfter(invoker, invocation, invokeResult);
                                await pool.Recovery(client);
                                goodUrls.Add(invoker);
                                return(invokeResult);
                            }
                            catch (Exception ex)
                            {
                                await pool.DestoryClient(client);
                                _source.WriteConsumerError(invoker, invocation, ex);
                                throw ex;
                            }
                        }
                        catch (Exception e)
                        {
                            badUrls.Add(new BadUrl {
                                Url = invoker, BadTime = DateTime.Now, CurrentException = e
                            });
                            return(new RpcResult <T>(e));
                        }
                    });
                    results.Add(invoker.ServiceKey, task);
                }

                var resultList = new List <IResult <T> >(results.Count);
                int timeout    = address.GetMethodParameter(invocation.MethodInfo.Name, TIMEOUT_KEY, DEFAULT_TIMEOUT);

                Task.WaitAll(results.Values.ToArray(), timeout);
                foreach (var entry in results)
                {
                    var r = await entry.Value;
                    if (r.HasException)
                    {
                        Logger().LogError(r.Exception, $"Invoke {entry.Key} {getGroupDescFromServiceKey(entry.Key)}  failed: {r.Exception.Message}");
                        return(new ClusterResult <T>(new RpcResult <T>(r.Exception), goodUrls, badUrls, r.Exception, true));
                    }
                    else
                    {
                        resultList.Add(r);
                    }
                }

                watch.Stop();

                if (resultList.Count == 0)
                {
                    return(new ClusterResult <T>(new RpcResult <T>(watch.ElapsedMilliseconds), goodUrls, badUrls, null, false));
                }
                else if (resultList.Count == 1)
                {
                    return(new ClusterResult <T>(resultList[0], goodUrls, badUrls, null, false));
                }

                if (returnType == typeof(void))
                {
                    return(new ClusterResult <T>(new RpcResult <T>(watch.ElapsedMilliseconds), goodUrls, badUrls, null, false));
                }

                if (merger.StartsWith("."))
                {
                    merger = merger.Substring(1);
                    MethodInfo method;
                    try
                    {
                        method = returnType.GetMethod(merger, new[] { returnType });
                    }
                    catch (Exception e)
                    {
                        var ex = new RpcException($"Can not merge result because missing method [{merger}] in class [{returnType.Name}]{e.Message}", e);
                        return(new ClusterResult <T>(new RpcResult <T>(ex), goodUrls, badUrls, ex, true));
                    }

                    if (method == null)
                    {
                        var ex = new RpcException($"Can not merge result because missing method [ {merger} ] in class [ {returnType.Name} ]");
                        return(new ClusterResult <T>(new RpcResult <T>(ex), goodUrls, badUrls, ex, true));
                    }

                    //if (!method.IsPublic)
                    //{
                    //method.setAccessible(true);
                    //}
                    resultValue = resultList[0].Value;
                    resultList.RemoveAt(0);
                    try
                    {
                        if (method.ReturnType != typeof(void) &&
                            method.ReturnType.IsAssignableFrom(resultValue.GetType()))
                        {
                            foreach (var r in resultList)
                            {
                                resultValue = method.Invoke(resultValue, new object[] { r.Value });
                            }
                        }
                        else
                        {
                            foreach (var r in resultList)
                            {
                                method.Invoke(resultValue, new object[] { r.Value });
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        var ex = new RpcException($"Can not merge result: {e.Message}", e);
                        return(new ClusterResult <T>(new RpcResult <T>(ex), goodUrls, badUrls, ex, true));
                    }
                }
                else
                {
                    IMerger resultMerger;
                    if (merger.ToLower() == "true" || merger.ToLower() == "default")
                    {
                        resultMerger = MergerFactory.GetMerger(returnType, _defaultMergers);
                    }
                    else
                    {
                        resultMerger = _mySelfMergers[merger];
                    }

                    if (resultMerger != null)
                    {
                        var rets = new List <object>(resultList.Count);
                        foreach (var r in resultList)
                        {
                            rets.Add(r.Value);
                        }
                        resultValue = resultMerger.GetType().GetMethod("Merge", new Type[] { returnType }).Invoke(resultMerger, new[] { rets });
                    }
                    else
                    {
                        var ex = new RpcException("There is no merger to merge result.");
                        return(new ClusterResult <T>(new RpcResult <T>(ex), goodUrls, badUrls, ex, true));
                    }
                }
                return(new ClusterResult <T>(new RpcResult <T>((T)resultValue.ChangeType(typeof(T)), watch.ElapsedMilliseconds), goodUrls, badUrls, null, false));
            }
            catch (Exception ex)
            {
                Debug.Print(ex.StackTrace);
                throw ex;
            }
            finally
            {
                if (watch.IsRunning)
                {
                    watch.Stop();
                }
            }
        }