Обработка сокетов в ASP.NET Core. Перевод на хостинг IIS
Есть проект, написанный на ASP.NET Core 3.1 который переехал на .NET 6 (MVC).
В нем есть Kestrel который слушает определенный порт и при новом соединении внешних клиентов с сервером (клиенты представляют себе устройства которые по IP на определенный порт стучаться и передают состояние), может быть сотни подключений, попадает в handler через UseConnectionHandler
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel(options =>
{
options.ListenAnyIP(7890, _o => _o.UseConnectionHandler<HeadConnectionHandler>());
options.ListenAnyIP(80);
});
webBuilder.UseIISIntegration();
webBuilder
.UseSockets(_s => { _s.NoDelay = false; })
.UseStartup<Startup>();
});
Есть обычный порт 80 - по которому работает обычный сайт. Проект крутится на виндовом сервере, через публикацию переносимой версии и зависимости от платформы. Запускается через exe в режиме автономности, при запуске exe файла сборки, все работает.
Публикую в IIS, сайт запускается, но прослушивание порта и переход в HeadConnectionHandler - не происходит.
Как правильно настроить работу сервиса, чтобы работал код аналогичный в месте где используется Kestrel?
UPD. I need help :)
Ответы (1 шт):
Вызов UseIISIntegration делает, упрощённо говоря, следующее:
- Проверяет переменные окружения ASPNETCORE_*, на наличие
- Если их нет - не делает ничего
- Если они есть - то затирает настройки конечных точек Kestrel, заставляя его слушать указанный в переменных окружения порт, а также применяет ещё несколько настроек
Если вам надо открыть дополнительный порт с отдельными настройками - это можно сделать примерно так:
- Убедитесь что вы создаёте ваш хост либо веб-приложение без настроек по умолчанию, чтобы никто не вызвал
UseIISIntegration(); - Загляните в исходники
UseIISIntegration()чтобы повторить всё то что оно делает - но вручную и без переопределения настроек Kestrel; - Также не забудьте использовать переданные вам переменные окружения в настройках Kestrel;
- Когда будете добавлять StartupFilter с вспомогательными мидлварями - не забудьте исключить из его обработки запросы с дополнительной конечной точки (отличить одну конечную точку от другой можно с помощью коллекции Features, которую вы можете менять в вашем HeadConnectionHandler).
Но на самом деле это всё бесполезно, и знаете почему? Потому что IIS отвечает за запуск вашего процесса, и он запустит его только когда придёт запрос на порт 80. То есть, насколько я понял вашу архитектуру, пока первый пользователь не зайдёт на сайт - никакие устройства не смогут передать вам никакое состояние.
Это вообще не то поведение которое нужно в таких случаях!
Как сделать правильно.
Вариант 1:
Откажитесь от прямой публикации в IIS, и запускайте ваш сервер как системную службу, слушающую 127.0.0.1 на нестандартном порту. IIS можно настроить как прокси-сервер без автоматических интеграций.
Вариант 2.
Откажитесь от прямой публикации в IIS, и запускайте ваш сервер как системную службу, слушающую 80й порт напрямую. IIS выкиньте нафиг.
Вариант 3.
Откажитесь от Windows, настройте интеграцию с systemd и запускайте ваш сервер как systemd unit на Linux. Это позволит сэкономить на хостинге если вы хоститесь в облаке.