Использует ли Kestrel один поток для обработки запросов, таких как Node.js?

И Kestrel, и Node.js основаны на libuv < / а>.

Хотя в Node.js точно указано, что он использует цикл событий, я не могу найти, так ли это в случае с Kestrel, или если он использует пул потоков / очередь запросов, например IIS?

Пустельга за веб-сервером

Пустельга за веб-сервером

Цикл событий Node.js

    ┌───────────────────────┐
 ┌─>│        timers         │
 │  └──────────┬────────────┘
 │  ┌──────────┴────────────┐
 │  │     I/O callbacks     │
 │  └──────────┬────────────┘
 │  ┌──────────┴────────────┐
 │  │     idle, prepare     │
 │  └──────────┬────────────┘      ┌───────────────┐
 │  ┌──────────┴────────────┐      │   incoming:   │
 │  │         poll          │<─────┤  connections, │
 │  └──────────┬────────────┘      │   data, etc.  │
 │  ┌──────────┴────────────┐      └───────────────┘
 │  │        check          │
 │  └──────────┬────────────┘
 │  ┌──────────┴────────────┐
 └──┤    close callbacks    │
    └───────────────────────┘

person Noro Korny    schedule 03.12.2016    source источник


Ответы (2)


Обновлено для ASP.Net Core 2.0. Как указывает poke, сервер разделен между хостингом и транспортом, где libuv принадлежит транспортному уровню. Libuv ThreadCount был перемещен в свой собственный LibuvTransportOptions, и они устанавливаются отдельно в построителе веб-хоста с помощью метода UseLibuv() ext:

  • Если вы отметите _ 4_ в github, вы увидите параметр ThreadCount:

    /// <summary>
    /// The number of libuv I/O threads used to process requests.
    /// </summary>
    /// <remarks>
    /// Defaults to half of <see cref="Environment.ProcessorCount" /> rounded down and clamped between 1 and 16.
    /// </remarks>
    public int ThreadCount { get; set; } = ProcessorThreadCount;
    
  • Опцию можно установить при вызове UseLibuv в конструкторе веб-хоста. Например:

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseLibuv(opts => opts.ThreadCount = 4)
            .UseStartup<Startup>()                
            .Build();
    

В ASP.NET Core 1.X конфигурация Libuv была частью сервера пустельги:

  • Если вы проверите KestrelServerOptions в своем репозитории на github, вы увидите, что есть опция ThreadCount:

    /// <summary>
    /// The number of libuv I/O threads used to process requests.
    /// </summary>
    /// <remarks>
    /// Defaults to half of <see cref="Environment.ProcessorCount" /> rounded down and clamped between 1 and 16.
    /// </remarks>
    public int ThreadCount { get; set; } = ProcessorThreadCount;
    
  • Параметр можно установить в вызове UseKestrel, например, в новом приложении ASP.Net Core:

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel(opts => opts.ThreadCount = 4)
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
    
        host.Run();
    }
    

Копаемся в исходном коде:

  • Вы можете увидеть потоки слушателя libuv (или _ 14_) создается в _ 15_
  • В некоторых местах будет называться _ 16_, чтобы они могли запускать код в пуле потоков CLR вместо потоков libuv. (Используется ThreadPool.QueueUserWorkItem). Похоже, что пул установлен по умолчанию с максимум 32K потоков, который может быть изменен через config.
  • Frame<TContext> делегирует фактическому приложению (например, приложению ASP.Net Core) для обработки запроса.

Таким образом, можно сказать, что он использует несколько циклов событий libuv для ввода-вывода. Фактическая работа выполняется над управляемым кодом с помощью стандартных рабочих потоков с использованием пула потоков CLR.

Я хотел бы найти более авторитетную документацию по этому поводу (официальные документы не давайте подробностей). Лучшее, что я нашел, - это Дэмиан Эдвардс, рассказывающий о Kestrel на канал 9. Примерно на 12-й минуте он объясняет:

  • libuv использует однопоточную модель цикла событий
  • Kestrel поддерживает несколько циклов событий
  • Kestrel выполняет только операции ввода-вывода в циклах событий libuv
  • Вся работа, не связанная с вводом-выводом (включая все, что связано с HTTP, например, синтаксический анализ, фрейминг и т. Д.), Выполняется в управляемом коде в стандартных рабочих потоках .net.

Вдобавок вернул быстрый поиск:

  • Дэвид Фаулер рассказывает о пуле потоков в Kestrel здесь. Это также подтверждает, что запрос все еще может переходить между потоками в ASP.Net Core. (как было в предыдущих версиях)
  • Этот блогпост глядя на пустельгу, когда она вышла
  • Этот вопрос об управлении потоками в ASP.Net Core.
person Daniel J.G.    schedule 03.12.2016
comment
В asp.net core 2.0 класс KestrelServerOptions не имеет свойства ThreadCount, как это установить? - person Mohammad Akbari; 10.10.2017
comment
В версии 2.0 сервер был разделен на серверный и транспортный уровень. Как часть этого, конфигурация подсчета потоков переместилась на транспортный уровень. Таким образом, эквивалентным решением для этого ответа является настройка _ 1_ с использованием _ 2_. - person poke; 10.10.2017
comment
Спасибо @poke, как только у меня появится свободное время, я постараюсь обновить ответ на различия 1.X vs 2.0 - person Daniel J.G.; 10.10.2017
comment
@ DanielJ.G. Это действительно единственная разница, о которой я могу думать :) - person poke; 10.10.2017
comment
сейчас нет UseLibuv () - person mugi; 09.08.2019
comment
@mugi, пожалуйста, проверьте решение на stackoverflow.com/questions/57708071/ - person Kamran Shahid; 30.08.2019

Потоки зависят от транспорта. С транспортом libuv (по умолчанию в 2.0), как указано в ответе Daniel JG, существует ряд циклов событий на основе количество логических процессоров на машине, и это можно изменить, задав значение в параметрах. По умолчанию каждое соединение привязано к определенному потоку, и все операции ввода-вывода выполняются в этом потоке. Код пользователя выполняется в потоках пула потоков, потому что мы не верим, что пользователи не будут блокировать потоки ввода-вывода. Когда вы выполняете вызовы ввода-вывода для этих потоков пула потоков (т.е. HttpResponse.WriteAsync), пустельга выполняет работу по маршалированию этого потока обратно в соответствующий поток ввода-вывода, к которому был привязан сокет. Типичный поток запросов выглядит так:

[чтение из сети] отправка в пул потоков -> [анализ http], [выполнение конвейера промежуточного программного обеспечения] вызов для записи -> постановка пользовательской работы в очередь в поток ввода-вывода [запись в сеть]

Конечно, вы всегда можете сказать kestrel, что вы профессионал, и никогда не будете блокировать поток ввода-вывода и запускать на нем свой код. Но я бы не стал, если бы не знал, что делаю (а я не знаю: D).

person davidfowl    schedule 17.11.2017