Windows run service in background

Реализация фоновых задач в микрослужбах с помощью IHostedService и класса BackgroundService Implement background tasks in microservices with IHostedService and the BackgroundService class

Фоновые задачи и запланированные задания обычно требуется использовать в любом приложении независимо от того, строится ли оно на основе архитектуры микрослужб. Background tasks and scheduled jobs are something you might need to use in any application, whether or not it follows the microservices architecture pattern. Разница при использовании архитектуры микрослужб в том, что вы можете реализовать фоновую задачу в отдельном процессе или контейнере, чтобы затем масштабировать его по мере необходимости. The difference when using a microservices architecture is that you can implement the background task in a separate process/container for hosting so you can scale it down/up based on your need.

Если посмотреть шире, в .NET такие задачи называются размещенными службами, так как они представляют собой службы или логику, размещаемые в узле, приложении или микрослужбе. From a generic point of view, in .NET we called these type of tasks Hosted Services, because they are services/logic that you host within your host/application/microservice. Обратите внимание на то, что в этом случае под размещенной службой понимается просто класс с логикой фоновой задачи. Note that in this case, the hosted service simply means a class with the background task logic.

Начиная с версии .NET Core 2.0, платформа предоставляет новый интерфейс IHostedService, который позволяет легко реализовывать размещенные службы. Since .NET Core 2.0, the framework provides a new interface named IHostedService helping you to easily implement hosted services. Главная идея заключается в том, что вы можете регистрировать несколько фоновых задач (размещенных служб), которые выполняются в фоновом режиме в процессе работы веб-узла или обычного узла, как показано на рис. 6-26. The basic idea is that you can register multiple background tasks (hosted services) that run in the background while your web host or host is running, as shown in the image 6-26.

Рис. 6-26. Figure 6-26. Использование интерфейса IHostedService в классах WebHost и Host Using IHostedService in a WebHost vs. a Host

ASP.NET Core версий 1.x и 2.x поддерживает IWebHost для фоновых процессов в веб-приложениях. ASP.NET Core 1.x and 2.x support IWebHost for background processes in web apps. .NET Core 2.1 и более поздних версий поддерживает IHost для фоновых процессов с простыми консольными приложениями. .NET Core 2.1 and later versions support IHost for background processes with plain console apps. Обратите внимание на различие между WebHost и Host . Note the difference made between WebHost and Host .

WebHost (базовый класс, реализующий интерфейс IWebHost ) в ASP.NET Core 2.0 — это артефакт инфраструктуры, с помощью которого процесс получает доступ к возможностям сервера HTTP, например при реализации веб-приложения MVC или службы веб-интерфейса API. A WebHost (base class implementing IWebHost ) in ASP.NET Core 2.0 is the infrastructure artifact you use to provide HTTP server features to your process, such as when you’re implementing an MVC web app or Web API service. Он предоставляет все новые преимущества инфраструктуры в ASP.NET Core, позволяя использовать внедрение зависимостей, вставлять промежуточные слои в конвейер запросов и т. д. It provides all the new infrastructure goodness in ASP.NET Core, enabling you to use dependency injection, insert middlewares in the request pipeline, and similar. WebHost использует те же IHostedServices для фоновых задач. The WebHost uses these very same IHostedServices for background tasks.

Читайте также:  Восстановление net framework windows 10

Объект Host (базовый класс, реализующий IHost ) впервые появился в .NET Core 2.1. A Host (base class implementing IHost ) was introduced in .NET Core 2.1. По существу, класс Host обеспечивает практически такую же инфраструктуру, что и класс WebHost (внедрение зависимостей, размещенные службы и т. д.), но в этом случае узел должен представлять собой более простой процесс без связанных с MVC веб-интерфейсами API или сервером HTTP возможностей. Basically, a Host allows you to have a similar infrastructure than what you have with WebHost (dependency injection, hosted services, etc.), but in this case, you just want to have a simple and lighter process as the host, with nothing related to MVC, Web API or HTTP server features.

Таким образом, вы можете либо создать специальный хост-процесс с помощью IHost для реализации только размещенных служб, например микрослужбу, предназначенную для размещения IHostedServices , либо расширить существующий в ASP.NET Core класс WebHost , например существующий веб-интерфейс API ASP.NET Core или приложение MVC. Therefore, you can choose and either create a specialized host-process with IHost to handle the hosted services and nothing else, such a microservice made just for hosting the IHostedServices , or you can alternatively extend an existing ASP.NET Core WebHost , such as an existing ASP.NET Core Web API or MVC app.

Каждый подход имеет свои преимущества и недостатки в зависимости от потребностей бизнеса и требований к масштабируемости. Each approach has pros and cons depending on your business and scalability needs. Основной принцип заключается в том, что если фоновые задачи не связаны с HTTP ( IWebHost ), следует использовать интерфейс IHost . The bottom line is basically that if your background tasks have nothing to do with HTTP ( IWebHost ) you should use IHost .

Регистрация размещенных служб в WebHost или Host Registering hosted services in your WebHost or Host

Давайте более подробно разберем интерфейс IHostedService , так как его использование в классах WebHost и Host во многом схоже. Let’s drill down further on the IHostedService interface since its usage is pretty similar in a WebHost or in a Host .

Библиотека SignalR — один из примеров артефактов, использующих размещенные службы, однако ее можно применять и для более простых задач, таких как следующие: SignalR is one example of an artifact using hosted services, but you can also use it for much simpler things like:

  • фоновая задача опроса базы данных для поиска изменений; A background task polling a database looking for changes.
  • запланированная задача для периодического обновления кэша; A scheduled task updating some cache periodically.
  • реализация QueueBackgroundWorkItem, которая позволяет задаче выполняться в фоновом потоке; An implementation of QueueBackgroundWorkItem that allows a task to be executed on a background thread.
  • обработка сообщений из очереди сообщений веб-приложения в фоновом режиме при использовании общих служб, таких как ILogger ; Processing messages from a message queue in the background of a web app while sharing common services such as ILogger .
  • фоновая задача, запускаемая с помощью Task.Run() . A background task started with Task.Run() .

Выполнение любого из этих действий можно перенести в фоновую задачу, которая реализует IHostedService . You can basically offload any of those actions to a background task that implements IHostedService .

Для добавления одного или нескольких экземпляров IHostedServices в WebHost или Host их следует зарегистрировать посредством метода расширения AddHostedService в классе ASP.NET Core WebHost (или в классе Host в .NET Core 2.1 и более поздних версий). The way you add one or multiple IHostedServices into your WebHost or Host is by registering them up through the AddHostedService extension method in an ASP.NET Core WebHost (or in a Host in .NET Core 2.1 and above). Фактически размещенные службы регистрируются в известном методе ConfigureServices() класса Startup , как в следующем коде типичного класса ASP.NET WebHost: Basically, you have to register the hosted services within the familiar ConfigureServices() method of the Startup class, as in the following code from a typical ASP.NET WebHost.

В этом коде размещенная служба GracePeriodManagerService представляет собой реальный код микрослужбы размещения заказов в приложении eShopOnContainers, а другие две службы — это просто дополнительные примеры. In that code, the GracePeriodManagerService hosted service is real code from the Ordering business microservice in eShopOnContainers, while the other two are just two additional samples.

Читайте также:  Частота обновления экрана монитора windows

Выполнение фоновой задачи IHostedService согласуется с временем существования приложения (узла или микрослужбы). The IHostedService background task execution is coordinated with the lifetime of the application (host or microservice, for that matter). Задачи регистрируются при запуске приложения, а при завершении его работы есть возможность произвести надлежащую обработку или очистку. You register tasks when the application starts and you have the opportunity to do some graceful action or clean-up when the application is shutting down.

Фоновый поток можно запускать для выполнения любой задачи и без использования IHostedService . Without using IHostedService , you could always start a background thread to run any task. Различие именно в том, что будет происходить при завершении работы приложения: поток будет просто завершаться без возможности надлежащей очистки. The difference is precisely at the app’s shutdown time when that thread would simply be killed without having the opportunity to run graceful clean-up actions.

Интерфейс IHostedService The IHostedService interface

При регистрации интерфейса IHostedService платформа .NET вызывает методы StartAsync() и StopAsync() типа IHostedService во время запуска и остановки приложения соответственно. When you register an IHostedService , .NET will call the StartAsync() and StopAsync() methods of your IHostedService type during application start and stop respectively. Дополнительные сведения см. в разделе Интерфейс IHostedService. For more details, refer IHostedService interface

Как было показано ранее, вы можете создать несколько реализаций IHostedService и зарегистрировать их в методе ConfigureService() в контейнере внедрения зависимостей. As you can imagine, you can create multiple implementations of IHostedService and register them at the ConfigureService() method into the DI container, as shown previously. Все эти размещенные службы будут запускаться и останавливаться вместе с приложением или микрослужбой. All those hosted services will be started and stopped along with the application/microservice.

Как разработчик, вы несете ответственность за обработку действия завершения своих служб при активации метода StopAsync() узлом. As a developer, you are responsible for handling the stopping action of your services when StopAsync() method is triggered by the host.

Реализация IHostedService с помощью пользовательского класса размещенной службы, производного от базового класса BackgroundService Implementing IHostedService with a custom hosted service class deriving from the BackgroundService base class

Можно пойти дальше и создать пользовательский класс размещенной службы с нуля, реализовав интерфейс IHostedService , как это требуется делать в .NET Core 2.0 и более поздних версий. You could go ahead and create your custom hosted service class from scratch and implement the IHostedService , as you need to do when using .NET Core 2.0 and later.

Но большинство фоновых задач имеют схожие потребности в отношении управления токенами отмены и других типичных операций, поэтому существует удобный абстрактный базовый класс BackgroundService , от которого можно создавать производные классы (доступно с .NET Core 2.1). However, since most background tasks will have similar needs in regard to the cancellation tokens management and other typical operations, there is a convenient abstract base class you can derive from, named BackgroundService (available since .NET Core 2.1).

Он будет выполнять основную часть работы, связанной с настройкой фоновой задачи. That class provides the main work needed to set up the background task.

Следующий код — это абстрактный базовый класс BackgroundService, реализованный в .NET. The next code is the abstract BackgroundService base class as implemented in .NET.

Благодаря такой унаследованной реализации при создании собственного класса размещенной службы, производного от приведенного выше абстрактного базового класса, необходимо просто реализовать в нем метод ExecuteAsync() . Пример представлен в следующем упрощенном коде из приложения eShopOnContainers, который опрашивает базу данных и при необходимости публикует события интеграции в шине событий. When deriving from the previous abstract base class, thanks to that inherited implementation, you just need to implement the ExecuteAsync() method in your own custom hosted service class, as in the following simplified code from eShopOnContainers which is polling a database and publishing integration events into the Event Bus when needed.

Читайте также:  Поставить все обновления windows 10

В этом конкретном примере eShopOnContainers выполняет метод приложения, который отправляет запрос к таблице базы данных для поиска заказов с определенным состоянием, а при применении изменений публикует события интеграции через шину событий (она может быть основана на RabbitMQ или служебной шине Azure). In this specific case for eShopOnContainers, it’s executing an application method that’s querying a database table looking for orders with a specific state and when applying changes, it is publishing integration events through the event bus (underneath it can be using RabbitMQ or Azure Service Bus).

Естественно, вместо этого можно выполнять любую другую фоновую бизнес-задачу. Of course, you could run any other business background task, instead.

По умолчанию для токена отмены задается время ожидания, равное 5 секундам, хотя это значение можно изменить при создании WebHost с помощью расширения UseShutdownTimeout интерфейса IWebHostBuilder . By default, the cancellation token is set with a 5 seconds timeout, although you can change that value when building your WebHost using the UseShutdownTimeout extension of the IWebHostBuilder . Это означает, что отмена службы ожидается в течение 5 секунд. В противном случае ее работа будет завершена внезапно. This means that our service is expected to cancel within 5 seconds otherwise it will be more abruptly killed.

В следующем коде это время изменяется на 10 секунд: The following code would be changing that time to 10 seconds.

Сводная диаграмма классов Summary class diagram

На приведенном ниже рисунке представлена наглядная сводка классов и интерфейсов, которые задействованы в реализации IHostedService. The following image shows a visual summary of the classes and interfaces involved when implementing IHostedServices.

Рис. 6-27. Figure 6-27. Диаграмма классов и интерфейсов, связанных с IHostedService Class diagram showing the multiple classes and interfaces related to IHostedService

Диаграмма классов: IWebHost и IHost могут разместить много служб, наследующих от BackgroundService, который реализует IHostedService. Class diagram: IWebHost and IHost can host many services, which inherit from BackgroundService, which implements IHostedService.

Основные положения и моменты, связанные с развертыванием Deployment considerations and takeaways

Важно отметить, что способ развертывания узла WebHost в ASP.NET Core или Host в .NET может влиять на конечное решение. It is important to note that the way you deploy your ASP.NET Core WebHost or .NET Host might impact the final solution. Например, если вы развертываете WebHost в службах IIS или обычной службе приложений Azure, работа узла может быть завершена из-за перезапуска пула приложений. For instance, if you deploy your WebHost on IIS or a regular Azure App Service, your host can be shut down because of app pool recycles. Однако если вы развертываете узел как контейнер в оркестраторе, таком как Kubernetes, вы можете контролировать гарантированное число активных экземпляров узла. But if you are deploying your host as a container into an orchestrator like Kubernetes, you can control the assured number of live instances of your host. Кроме того, в облачной среде можно рассмотреть другие подходы, особенно предназначенные для таких сценариев, как Функции Azure. In addition, you could consider other approaches in the cloud especially made for these scenarios, like Azure Functions. Если же требуется, чтобы служба работала постоянно и была развернута в Windows Server, используйте службу Windows. Finally, if you need the service to be running all the time and are deploying on a Windows Server you could use a Windows Service.

Даже при развертывании WebHost в пуле приложений применим ряд сценариев, таких как повторное заполнение или сброс кэша в памяти для приложения. But even for a WebHost deployed into an app pool, there are scenarios like repopulating or flushing application’s in-memory cache that would be still applicable.

Оцените статью