简体   繁体   中英

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

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM