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)); }
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(); } } }