Changing HTTP.sys kernel queue limit when using .Net HttpListener?
Asked Answered
L

1

5

I have an application that uses the HttpListener class in .Net 4.0 to service http requests.

Under load I have noticed that I get 503 - QueueFull - errors reported in the log. A search for this error suggests that it occurs when the maximum number of requests that http.sys will queue has been exceeded.

The default queue length is 1000. If you are using IIS this seems to be tuneable via the "Queue Length" parameter in Advanced Settings on the Application Pool.

If you are NOT using IIS is there any way of tuning this value? Or is the control of this parameter hidden in the HttpListener class and not exposed to developers?

Legitimize answered 14/3, 2013 at 18:13 Comment(2)
Have you tried setting the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\MaxConcurrentRequestsPerCPU to something larger? (blogs.msdn.com/b/tmarq/archive/2007/07/21/…) or any of the registry entries here support.microsoft.com/kb/820129Brachypterous
Thanks for the response Chris. I haven't had a chance yet to try the settings, however, the blog does suggest that the http.sys kernel queue is different to what MaxConcurrentRequestsPerCPU is affecting. I had looked at the registry settings for http.sys before and none of the descriptions say they will alter the queue lengthLegitimize
H
9

It seems that the HttpListener doesn't allow to change the HttpServerQueueLengthProperty property directly. And by default this property is set to 1000.

But you can try to set it manually after HttpListener start. It's hack, because it uses internal property RequestQueueHandle of HttpListener, so use it at your peril.

Hack:

using System;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;

namespace Network.Utils
{
    public static class HttpApi
    {
        public unsafe static void SetRequestQueueLength(HttpListener listener, long len)
        {
            var listenerType = typeof (HttpListener);
            var requestQueueHandleProperty = listenerType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).First(p => p.Name == "RequestQueueHandle");

            var requestQueueHandle = (CriticalHandle)requestQueueHandleProperty.GetValue(listener);
            var result = HttpSetRequestQueueProperty(requestQueueHandle, HTTP_SERVER_PROPERTY.HttpServerQueueLengthProperty, new IntPtr((void*)&len), (uint)Marshal.SizeOf(len), 0, IntPtr.Zero);

            if (result != 0)
            {
                throw new HttpListenerException((int) result);
            }
        }

        internal enum HTTP_SERVER_PROPERTY
        {
            HttpServerAuthenticationProperty,
            HttpServerLoggingProperty,
            HttpServerQosProperty,
            HttpServerTimeoutsProperty,
            HttpServerQueueLengthProperty,
            HttpServerStateProperty,
            HttpServer503VerbosityProperty,
            HttpServerBindingProperty,
            HttpServerExtendedAuthenticationProperty,
            HttpServerListenEndpointProperty,
            HttpServerChannelBindProperty,
            HttpServerProtectionLevelProperty,
        }

        [DllImport("httpapi.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        internal static extern uint HttpSetRequestQueueProperty(
            CriticalHandle requestQueueHandle,
            HTTP_SERVER_PROPERTY serverProperty,
            IntPtr pPropertyInfo,
            uint propertyInfoLength,
            uint reserved,
            IntPtr pReserved);         
    }
}

Usage example:

using (var listener = new HttpListener())
{
    listener.Prefixes.Add("http://*:8080/your/service/");
    listener.Start();

    Network.Utils.HttpApi.SetRequestQueueLength(listener, 5000);

    // ...
}

After application start you can check the queue length by running this command:

netsh http show servicestate

Check "Max requests" property for your process. Now it has to be equal to 5000.

Homer answered 8/5, 2013 at 10:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.