예제 #1
0
        /// <summary>
        /// Ping.
        /// </summary>
        public void Ping()
        {
            var pool = ConnectionPoolManager.GetPool(this.Host, this.Port, this.Timeout);
            ThriftSConnection connection = null;

            try
            {
                connection = pool.Borrow();

                var xrequest = new ThriftSRequest();
                xrequest.Headers        = new Dictionary <string, string>();
                xrequest.ClientHostName = Environment.MachineName;
                xrequest.ClientIP       = connection.LocalAddress.ToString();

                connection.Client.Ping(xrequest);
            }
            catch (TTransportException exception)
            {
                pool.ReportError(connection, exception);
                throw;
            }
            catch (TProtocolException exception)
            {
                pool.ReportError(connection, exception);
                throw;
            }
            catch (SocketException exception)
            {
                pool.ReportError(connection, exception);
                throw;
            }
            catch (IOException exception)
            {
                pool.ReportError(connection, exception);
                throw;
            }
            finally
            {
                pool.Release(connection);
            }
        }
예제 #2
0
        /// <summary>
        /// Invokes the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns>IMessage.</returns>
        public override IMessage Invoke(IMessage message)
        {
            var mcm = (IMethodCallMessage)message;
            IMethodReturnMessage returnMessage = null;

            if (mcm.MethodBase.IsDefined(typeof(ThriftSOperationAttribute), false) == false)
            {
                throw new ThriftSException(string.Format("Missing ThriftSOperationAttribute in '{0}.{1}'.", this.ServiceName, mcm.MethodName));
            }

            object returnValue = null;

            var stopwatch = new Stopwatch();

            string invokeDesc = string.Format("调用{0}契约的{1}方法", this.ServiceName, mcm.MethodName);

            // 构造请求
            var srequest = new ThriftSRequest()
            {
                ServiceName = this.ServiceName,
                MethodName  = Utils.GetMethodName((MethodInfo)mcm.MethodBase),
                Headers     = new Dictionary <string, string>(),
                Parameters  = new List <ThriftSParameter>()
            };

            srequest.Uri            = string.Format("thrift://{0}:{1}/{2}/{3}", this.Host, this.Port, this.ServiceShortName, srequest.MethodName);
            srequest.Version        = Utils.Version;
            srequest.ClientPid      = this.ClientPid;
            srequest.ClientHostName = this.ClientHostName;
            srequest.ClientRuntime  = ".NET " + Environment.Version.ToString();

            try
            {
                // 计时开始
                stopwatch.Start();
                if (mcm.Args != null)
                {
                    for (var i = 0; i < mcm.Args.Length; i++)
                    {
                        var argument = mcm.Args[i];

                        ThriftSParameter parameter = null;
                        if (argument == null)
                        {
                            parameter = new ThriftSParameter()
                            {
                                Index       = (sbyte)i,
                                Name        = string.Empty,
                                Type        = string.Empty,
                                Compression = ThriftSCompression.None,
                                ContentType = ContentTypes.Binary,
                                HasValue    = false
                            };
                        }
                        else
                        {
                            parameter = new ThriftSParameter()
                            {
                                Index       = (sbyte)i,
                                Name        = string.Empty,
                                Type        = string.Empty,
                                Compression = ThriftSCompression.None,
                                ContentType = ContentTypes.Thrift,
                                HasValue    = true,
                                Value       = ThriftSerializer.Serialize(argument)
                            };
                        }

                        // 大于10K开启压缩
                        if (parameter.Value != null && parameter.Value.Length > 10 * 1024)
                        {
                            parameter.Value       = Utils.GzipCompress(parameter.Value);
                            parameter.Compression = ThriftSCompression.Gzip;
                        }

                        srequest.Parameters.Add(parameter);
                    }
                }

                ThriftSResponse sresponse = null;
                try
                {
                    var xpool = ConnectionPoolManager.GetPool(this.Host, this.Port, this.Timeout);
                    ThriftSConnection xconnection     = null;
                    TimeSpan          connectTookTime = TimeSpan.MinValue;
                    try
                    {
                        DateTime beginConnectTime = DateTime.Now;
                        xconnection     = xpool.Borrow();
                        connectTookTime = beginConnectTime - DateTime.Now;

                        if (string.IsNullOrEmpty(this.ClientIP))
                        {
                            this.ClientIP = xconnection.LocalAddress.ToString();
                        }

                        srequest.ClientIP = this.ClientIP;
                        sresponse         = xconnection.Client.Process(srequest);
                    }
                    catch (SocketException exception)
                    {
                        xpool.ReportError(xconnection, exception);
                        this.HandleException("SocketException", invokeDesc, srequest, exception);
                    }
                    catch (IOException exception)
                    {
                        xpool.ReportError(xconnection, exception);
                        var socketException = exception.InnerException as SocketException;
                        if (socketException != null)
                        {
                            this.HandleException("SocketException", invokeDesc, srequest, socketException);
                        }

                        this.HandleException("IOException", invokeDesc, srequest, exception);
                    }
                    catch (TTransportException exception)
                    {
                        xpool.ReportError(xconnection, exception);

                        // 5秒以内的timeout认为是服务器积极拒绝.
                        if (exception.Message.StartsWith("Connect timed out") &&
                            connectTookTime.TotalSeconds < 5)
                        {
                            // 处理异常
                            this.HandleException(
                                "TTransportException",
                                invokeDesc,
                                srequest,
                                new TTransportException(exception.Type, "Service unavailable."));
                        }
                        else
                        {
                            this.HandleException("TTransportException", invokeDesc, srequest, exception);
                        }
                    }
                    catch (TProtocolException exception)
                    {
                        xpool.ReportError(xconnection, exception);
                        this.HandleException("TProtocolException", invokeDesc, srequest, exception);
                    }
                    finally
                    {
                        // 内部Try可以更快的释放连接。
                        xpool.Release(xconnection);
                    }

                    // 非void且result非空
                    if (sresponse != null && sresponse.Result != null)
                    {
                        // 解压
                        if (sresponse.Result.Compression == ThriftSCompression.Gzip)
                        {
                            sresponse.Result.Data = Utils.GzipUnCompress(sresponse.Result.Data);
                        }

                        if (sresponse.Result.ContentType == ContentTypes.Thrift)
                        {
                            returnValue = ThriftSerializer.Deserialize(
                                ((MethodInfo)mcm.MethodBase).ReturnType,
                                sresponse.Result.Data);
                        }
                        else
                        {
                            throw new NotSupportedException(string.Format("Not supported content type: {0}", sresponse.Result.ContentType));
                        }
                    }

                    returnMessage = new ReturnMessage(returnValue, null, 0, mcm.LogicalCallContext, mcm);
                }
                catch (TApplicationException tapplicationException)
                {
                    var info      = string.Format("tapplication exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(info + tapplicationException.Message, tapplicationException);

                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (BadRequestException badRequestException)
                {
                    var info      = string.Format("Bad request exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(
                        info + badRequestException.ErrorMessage,
                        info + Environment.NewLine + badRequestException.ErrorMessage);

                    // 远端异常使用ReturnMessage包装
                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (InternalServerException internalServerException)
                {
                    var info      = string.Format("Server internal exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(
                        info + internalServerException.ErrorMessage,
                        info + Environment.NewLine + internalServerException.ErrorDescription);

                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (InvocationException invocationException)
                {
                    var info      = string.Format("Server invocation exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(
                        info + invocationException.ErrorMessage,
                        info + Environment.NewLine + invocationException.ErrorDescription);

                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (Exception exception)
                {
                    this.HandleException("Exception", invokeDesc, srequest, exception);
                }
            }
            finally
            {
                stopwatch.Stop();
            }

            return(returnMessage);
        }