Подтвердить что ты не робот

Является ли Kestrel одним потоком для обработки запросов типа Node.js?

Оба Kestrel и Node.js основаны на libuv.

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

Kestrel за веб-сервером

Kestrel за веб-сервером

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

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

Ответ 1

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

  • Если вы проверите класс LibuvTransportOptions в 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 был частью сервера kestrel:

  • Если вы проверите класс KestrelServerOptions в его 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 (или KestrelThreads), создаваемые в KestrelEngine
  • В некоторых местах будут вызываться методы ThreadPool чтобы они могли запускать код в пуле потоков CLR вместо потоков libuv. (Используя ThreadPool.QueueUserWorkItem). Кажется, что пул по умолчанию имеет максимум 32K потоков, которые можно изменить через config.
  • Frame<TContext> делегирует фактическое приложение (например, Frame<TContext> приложение ASP.Net) для обработки запроса.

Таким образом, мы могли бы сказать, что он использует несколько циклов libuv для IO. Фактическая работа выполняется над управляемым кодом со стандартными рабочими потоками с использованием пула потоков CLR.

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

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

Кроме того, быстрый поиск вернулся:

  • Дэвид Фаулер говорит о пуле потоков в Kestrel здесь. Это также подтверждает, что запрос может все еще перемещаться между потоками в ASP.Net Core. (как это было в предыдущих версиях)
  • Этот блог пост, глядя на Kestrel, когда он вышел
  • Этот вопрос о том, как потоки управляются в ASP.Net Core.

Ответ 2

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

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

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

Ответ 3

Как вы делаете это в DotNet Core Aspnet 2.1?

.UseKestrel(opts => opts.ThreadCount = 4)

больше не поддерживается.

.UseLibuv(options => options.ThreadCount = 10 )

компилируется, но, похоже, ничего не меняет.

И я бы предпочел не использовать UseLibuv, мне не нужна эта маленькая разница в производительности, основная обработка