什么是HttpTransportElement的RequestInitializationTimeout? MSDN说:
获取或设置时间跨度,指定在超时之前请求初始化必须完成的时间。
究竟是什么"请求初始化"?为什么我要设置此属性?
答案 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'.
如果遵循源代码,我们可以在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
内部终止。
BeginProcessInboundRequest
和EndProcessInboundRequest
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}}。