为什么设置RequestInitializationTimeout属性?

时间:2015-06-17 19:40:12

标签: .net wcf

什么是HttpTransportElement的RequestInitializationTimeout? MSDN说:

  

获取或设置时间跨度,指定在超时之前请求初始化必须完成的时间。

究竟是什么"请求初始化"?为什么我要设置此属性?

1 个答案:

答案 0 :(得分:7)

没有关于RequestInitializationTimeout的明确文档。

SharedHttpTransportManager.IsCompatible的源代码中有关于RequestInitializationTimeout检查的注释:

// We are NOT checking the RequestInitializationTimeout here since the HttpChannelListener should be handle them
// individually. However, some of the scenarios might be impacted, e.g., if we have one endpoint with high RequestInitializationTimeout
// and the other is just normal, the first endpoint might be occupying all the receiving loops, then the requests to the normal endpoint
// will experience timeout issues. The mitigation for this issue is that customers should be able to increase the MaxPendingAccepts number.

如果我们检查将TimeoutException分配给OnParseComplete内部与requestException一起传递的HttpRequestContext.SetMessage(message, requestException),我们可以看到:

new TimeoutException(SR.GetString(
    SR.RequestInitializationTimeoutReached,
    this.HttpRequestContext.Listener.RequestInitializationTimeout,
    "RequestInitializationTimeout",
    typeof(HttpTransportBindingElement).Name))

和有关SR.RequestInitializationTimeoutReached System.Private.ServiceModel的异常消息是:

The initialization process of the request message timed out after {0}. To increase this quota, use the '{1}' property on the '{2}'.

将被格式化为以下格式:

The initialization process of the request message timed out after 00:00:10. To increase this quota, use the 'RequestInitializationTimeout' property on the 'HttpTransportBindingElement'.

tl; dr

如果遵循源代码,我们可以在EmptyHttpPipeline中找到它的用法。

在构造器EmptyHttpPipeline.EmptyHttpPipeline

如果存在RequestInitializationTimeout TimeSpan而不是禁用它的default 00:00:00 ),则将IOThreadTimer设置为{{ 1}}设置为dueTime滴答声,将OnRequestInitializationTimeout TimeSpan回调和Action实际的this对象)设置为EmptyHttpPipeline

callbackState

何时检查?

在尝试通过取消EmptyHttpPipeline.OnParseComplete来调用requestInitializationTimer方法时进行检查。如果有一个计时器,并且之前已被取消或过期,它将创建一个if (this.httpRequestContext.Listener.RequestInitializationTimeout != HttpTransportDefaults.RequestInitializationTimeout) { this.requestInitializationTimer = new IOThreadTimer(onRequestInitializationTimeout, this, false); this.requestInitializationTimer.Set(this.httpRequestContext.Listener.RequestInitializationTimeout); } 并分配给TimeoutException,并将其与requestException一起传递给HttpPipeline.HttpRequestContext.SetMessage

message

正在OnParseComplete方法内使用EnqueueMessageAsyncResult.CompleteParseAndEnqueue protected override void OnParseComplete(Message message, Exception requestException) { if (!this.CancelRequestInitializationTimer() && requestException == null) { requestException = FxTrace.Exception.AsError(new TimeoutException(SR.GetString( SR.RequestInitializationTimeoutReached, this.HttpRequestContext.Listener.RequestInitializationTimeout, "RequestInitializationTimeout", typeof(HttpTransportBindingElement).Name))); } this.HttpRequestContext.SetMessage(message, requestException); } HandleParseIncomingMessage内部调用EnqueueMessageAsyncResult.End方法。调用EnqueueMessageAsyncResult时会创建EmptyHttpPipeline.BeginProcessInboundRequest对象,该对象在EmptyHttpPipeline.EndProcessInboundRequest内部终止。

BeginProcessInboundRequestEndProcessInboundRequest

AsyncCallback

EnqueueMessageAsyncResult.CompleteParseAndEnqueue

internal override IAsyncResult BeginProcessInboundRequest(
    ReplyChannelAcceptor replyChannelAcceptor,
    Action dequeuedCallback,
    AsyncCallback callback,
    object state)
{
    this.TraceBeginProcessInboundRequestStart();
    return new EnqueueMessageAsyncResult(replyChannelAcceptor, dequeuedCallback, this, callback, state);
}

internal override void EndProcessInboundRequest(IAsyncResult result)
{
    // It will trigger HandleParseIncomingMessage AsyncCallback,
    // that will call CompleteParseAndEnqueue
    EnqueueMessageAsyncResult.End(result);
    this.TraceProcessInboundRequestStop();
}

如何检查和取消?

正在使用CancelRequestInitializationTimer方法进行检查,如果没有设置计时器,则返回true;如果先前已取消,则返回false,否则调用void CompleteParseAndEnqueue(IAsyncResult result) { using (DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.BoundOperation(this.CallbackActivity) : null) { Exception requestException; Message message = this.pipeline.EndParseIncomingMesssage(result, out requestException); if ((message == null) && (requestException == null)) { throw FxTrace.Exception.AsError( new ProtocolException( SR.GetString(SR.MessageXmlProtocolError), new XmlException(SR.GetString(SR.MessageIsEmpty)))); } // Here the EmptyHttpPipeline.OnParseComplete is being invoked this.pipeline.OnParseComplete(message, requestException); this.acceptor.Enqueue(this.pipeline.HttpRequestContext, this.dequeuedCallback, true); } } 方法进行检查,如果已取消,则返回true;如果计时器过期,则返回false。

EmptyHttpPipeline.CancelRequestInitializationTimer

IOThreadTimer.Cancel

实际上取消了什么?

OnRequestInitializationTimeout方法内,我们可以看到它取消了protected bool CancelRequestInitializationTimer() { if (this.requestInitializationTimer == null) { return true; } if (this.requestInitializationTimerCancelled) { return false; } bool result = this.requestInitializationTimer.Cancel(); this.requestInitializationTimerCancelled = true; return result; } ,从而中止了HttpPipeline.httpRequestContext

EmptyHttpPipeline.OnRequestInitializationTimeout

HttpPipeline

HttpPipeline.Cancel

static void OnRequestInitializationTimeout(object obj)
{
    Fx.Assert(obj != null, "obj should not be null.");
    HttpPipeline thisPtr = (HttpPipeline)obj;
    thisPtr.Cancel();
}

何时获得EmptyHttpPipeline对象?

如果我们使用接受EmptyHttpPipeline且没有HttpPipeline.CreateHttpPipeline的静态TransportIntegrationHandler来设置public virtual void Cancel() { this.httpRequestContext.Abort(); } ,则会得到HttpRequestContext.HttpMessagesSupported

transportIntegrationHandler = null

CreateHttpPipeline上调用HttpRequestContext.InitializeHttpPipeline

HttpRequestContext.InitializeHttpPipeline

public static HttpPipeline CreateHttpPipeline(HttpRequestContext httpRequestContext, TransportIntegrationHandler transportIntegrationHandler, bool isWebSocketTransport)
{
    if (transportIntegrationHandler == null)
    {
        Fx.Assert(!isWebSocketTransport, "isWebSocketTransport should be false if there's no HTTP message handler existing.");

        if (httpRequestContext.HttpMessagesSupported)
        {
            return new HttpMessageSupportedHttpPipeline(httpRequestContext);
        }

        return new EmptyHttpPipeline(httpRequestContext);
    }

    return NormalHttpPipeline.CreatePipeline(httpRequestContext, transportIntegrationHandler, isWebSocketTransport);
}

使用HttpRequestContext requestContext

HttpContextReceivedAsyncResult内部的HttpContextReceivedAsyncResult<TListenerChannel>.ProcessHttpContextAsync传入HttpChannelListener<TListenerChannel>.transportIntegrationHandler构造函数)中调用

HttpContextReceivedAsyncResult<TListenerChannel>.ProcessHttpContextAsync

public void InitializeHttpPipeline(TransportIntegrationHandler transportIntegrationHandler)
{
    this.httpPipeline = HttpPipeline.CreateHttpPipeline(this, transportIntegrationHandler, this.IsWebSocketRequest);
}

结论

所有这些使我们得出以下结论:当创建AsyncCompletionResult ProcessHttpContextAsync() { bool abort = false; try { this.context.InitializeHttpPipeline(this.listener.transportIntegrationHandler); ... } ... } 时没有HttpPipeline且没有TransportIntegrationHandler的{​​{1}}时,则新的HttpMessagesSupported HttpRequestContext / EmptyHttpPipeline的对象将有一个超时(如果设置了RequestInitializationTimeout ,则为),并在{内使用BeginProcessInboundRequest设置消息时设置了异常{1}}。