Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="call"></param>
        /// <param name="retryLeft"></param>
        /// <returns></returns>
        private TResponse Call <TResponse>(Func <CallInvoker, TResponse> call, int retryLeft)
        {
            while (true)
            {
                var callInvoker = default(ServerCallInvoker);
                try
                {
                    if (_callInvokers != null)
                    {
                        var invokers = _strategy.GetCallInvokers(_options.ServiceName);
                        callInvoker = _callInvokers(invokers);
                    }
                    else
                    {
                        callInvoker = _strategy.GetCallInvoker(_options.ServiceName);
                    }


                    if (callInvoker == null)
                    {
                        throw new ArgumentNullException($"{_options.ServiceName}无可用节点");
                    }
                    if (callInvoker.Channel == null || callInvoker.Channel.State == ChannelState.TransientFailure)
                    {
                        throw new RpcException(new Status(StatusCode.Unavailable, $"Channel Failure"));
                    }

                    if (_options.Interceptors?.Count > 0)
                    {
                        return(call(callInvoker.Intercept(_options.Interceptors.ToArray())));
                    }
                    return(call(callInvoker));
                }
                catch (RpcException ex)
                {
                    // 服务不可用,拉入黑名单
                    if (ex.Status.StatusCode == StatusCode.Unavailable)
                    {
                        _strategy.Revoke(_options.ServiceName, callInvoker);
                    }

                    if (0 > --retryLeft)
                    {
                        throw new Exception($"status: {ex.StatusCode}, node: {callInvoker?.Channel?.Target}, message: {ex.Message}", ex);
                    }
                }
            }
        }