Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="message"></param>
        protected override void ChannelRead0(IChannelHandlerContext ctx, ThriftMessage message)
        {
            message.ProcessStartTimeTicks = DateTime.UtcNow.Ticks;
            CheckResponseOrderingRequirements(ctx, message);

            TNiftyTransport messageTransport = new TNiftyTransport(ctx.Channel, message, true);
            TTransportPair  transportPair    = TTransportPair.FromSingleTransport(messageTransport);
            TProtocolPair   protocolPair     = this._duplexProtocolFactory.GetProtocolPair(transportPair);
            TProtocol       inProtocol       = protocolPair.InputProtocol;
            TProtocol       outProtocol      = protocolPair.OutputProtocol;

            long        requestSequenceId = BlockReadingForOrderReponse(ctx);
            IByteBuffer buffer            = message.Buffer;

            buffer.Retain();

            _factory.StartNew(() => ProcessRequestAsync(requestSequenceId, ctx, message, messageTransport, inProtocol, outProtocol)
                              .ContinueWith(t =>
            {
                inProtocol.Dispose();
                outProtocol.Dispose();
                buffer.Release();
                messageTransport?.Dispose();
            }));
        }
Ejemplo n.º 2
0
        private async Task ProcessRequestAsync(
            long requestSequenceId,
            IChannelHandlerContext ctx,
            ThriftMessage message,
            TNiftyTransport messageTransport,
            TProtocol inProtocol,
            TProtocol outProtocol)
        {
            //Task.Run(() =>
            //{
            try
            {
                AtomicBoolean responseSent = new AtomicBoolean(false);
                // Use AtomicReference as a generic holder class to be able to mark it final
                // and pass into inner classes. Since we only use .get() and .set(), we don't
                // actually do any atomic operations.
                AtomicReference <ITimeout> expireTimeout = new AtomicReference <ITimeout>(null);
                try
                {
                    try
                    {
                        long timeRemaining = 0;
                        long timeElapsed   = (DateTime.UtcNow.Ticks - message.ProcessStartTimeTicks) / 10000;

                        if (_queueTimeoutMillis > 0)
                        {
                            if (timeElapsed >= _queueTimeoutMillis)
                            {
                                String error = "Task stayed on the queue for " + timeElapsed +
                                               " milliseconds, exceeding configured queue timeout of " + _queueTimeoutMillis +
                                               " milliseconds.";
                                _logger.LogWarning(error);
                                TApplicationException taskTimeoutException = new TApplicationException(
                                    ExceptionType.InternalError, error);
                                await SendTApplicationExceptionAsync(taskTimeoutException, ctx, message, requestSequenceId, messageTransport,
                                                                     inProtocol, outProtocol);

                                return;
                            }
                        }
                        else if (_taskTimeoutMillis > 0)
                        {
                            if (timeElapsed >= _taskTimeoutMillis)
                            {
                                String error = "Task stayed on the queue for " + timeElapsed +
                                               " milliseconds, exceeding configured task timeout of " + _taskTimeoutMillis +
                                               " milliseconds.";
                                _logger.LogWarning(error);
                                TApplicationException taskTimeoutException = new TApplicationException(
                                    ExceptionType.InternalError, error);
                                await SendTApplicationExceptionAsync(taskTimeoutException, ctx, message, requestSequenceId, messageTransport,
                                                                     inProtocol, outProtocol);

                                return;
                            }
                            else
                            {
                                timeRemaining = _taskTimeoutMillis - timeElapsed;
                            }
                        }

                        if (timeRemaining > 0)
                        {
                            expireTimeout.Value = _taskTimeoutTimer.NewTimeout(timeout =>
                            {
                                // The immediateFuture returned by processors isn't cancellable, cancel() and
                                // isCanceled() always return false. Use a flag to detect task expiration.
                                if (responseSent.CompareAndSet(false, true))
                                {
                                    TApplicationException ex = new TApplicationException(
                                        ExceptionType.InternalError,
                                        "Task timed out while executing."
                                        );
                                    // Create a temporary transport to send the exception
                                    var duplicateBuffer = message.Buffer.Duplicate();
                                    duplicateBuffer.ResetReaderIndex();
                                    using (TNiftyTransport temporaryTransport = new TNiftyTransport(
                                               ctx.Channel,
                                               duplicateBuffer,
                                               message.TransportType))
                                    {
                                        TProtocolPair protocolPair = _duplexProtocolFactory.GetProtocolPair(
                                            TTransportPair.FromSingleTransport(temporaryTransport));
                                        SendTApplicationExceptionAsync(ex, ctx, message,
                                                                       requestSequenceId,
                                                                       temporaryTransport,
                                                                       protocolPair.InputProtocol,
                                                                       protocolPair.OutputProtocol).GetAwaiter().GetResult();
                                    }
                                }
                            }, TimeSpan.FromMilliseconds(timeRemaining / 10000));
                        }
                        //SSL 部分暂时不处理
                        IConnectionContext connectionContext = ctx.Channel.GetConnectionContext();
                        IRequestContext    requestContext    = new NiftyRequestContext(connectionContext, inProtocol, outProtocol, messageTransport);
                        RequestContexts.SetCurrentContext(requestContext);
                        try
                        {
                            //关键部分:交给 Thrift 来处理二进制。
                            bool result = await _processorFactory.GetProcessor(messageTransport).ProcessAsync(inProtocol, outProtocol, requestContext);

                            DeleteExpirationTimer(expireTimeout.Value);
                            try
                            {
                                // Only write response if the client is still there and the task timeout
                                // hasn't expired.
                                if (ctx.Channel.Active && responseSent.CompareAndSet(false, true))
                                {
                                    ThriftMessage response = message.MessageFactory(
                                        messageTransport.OutBuffer);
                                    await WriteResponseAsync(ctx, response, requestSequenceId,
                                                             DispatcherContext.IsResponseOrderingRequired(ctx));
                                }
                            }
                            catch (Exception t)
                            {
                                this.OnDispatchException(ctx, t);
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(0, ex, "write response to client fault.");
                            DeleteExpirationTimer(expireTimeout.Value);
                            OnDispatchException(ctx, ex);
                        }
                    }
                    finally
                    {
                        RequestContexts.ClearCurrentContext();
                    }
                }
                catch (Exception ex)
                {
                    OnDispatchException(ctx, ex);
                    ex.ThrowIfNecessary();
                }
            }
            catch (Exception ex)
            {
                ex.ThrowIfNecessary();
            }

            //});
        }