9

I have a windows service for netcore 2.0 which is based on this example: https://www.stevejgordon.co.uk/running-net-core-generic-host-applications-as-a-windows-service

The main hosted service in my case is subscribed to a message queue and processes the messages sequentially (an event is raised by the queue api each time a new message appears). If any messages cannot be processed they are moved to a different queue to be retried (x number of times, with exponential back-off). And so this needs to be done on a separate thread so as not to cause delays on the processing of the main queue

Is it ok to configure 2 HostedServices:

var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<MyMsgProcessingService>();
                services.AddHostedService<MyRetryService>();
            });

This does start and it does hit the StartAsync method (on the IHostedService interface) of each service

Or are you only allowed to have (is a good idea to have) one IHostedService implementation?

If two is OK, will the work on the slow service hold up the wok on the main service?

If only one, is it best to just spin up another thread to do the work for the retry queue? And how would I ensure that the new thread lives for the whole time the service is running? a while loop seems inappropriate as I'm just waiting for an event to be raised

e.g.

public Task StartAsync(CancellationToken cancellationToken)
{
    Task t = Task.Run(() => ProcessRetrys(), cancellationToken);
ChrisCa
  • 10,876
  • 22
  • 81
  • 118
  • 3
    Had the same question and then found confirmation [in the MS Docs](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice#registering-hosted-services-in-your-webhost-or-host) that registering and hosting multiple services under one `IHost` is acceptable. – mdisibio Mar 06 '21 at 05:36

1 Answers1

5

Or are you only allowed to have (is a good idea to have) one IHostedService implementation?

You can have as many as you want. As long as you are okay with the fact that if the process goes down, everything in it (all of services) are too go down.

Second thing to consider is thread pool. Thread pool is common for all the services, so if one of them is hungry for threads, others could be impacted.

If two is OK, will the work on the slow service hold up the wok on the main service?

Depends on if one service waits data from another. And on type of communication between them. If it's synchronous, then the slowest thread will be the bottleneck.

And how would I ensure that the new thread lives for the whole time the service is running?

Create a foreground thread. About. How to configure. But you have to be careful and terminate such thread graceful when the app shuts down, handling it in StopAsync method invocation.

a while loop seems inappropriate as I'm just waiting for an event to be raised

Use non-blocking queues to communicate between services. I can't give you a link on a specific implementation, because there are plenty of them, but you can start another question to help you find an appropriate one.

cassandrad
  • 3,412
  • 26
  • 50
  • thanks.Currently I have one HostedService, which has two wrappers of a QueueClient injected to it via standard IoC. Each of which is waiting for an event to be raised from their respective queue (main and retries). When a message comes in the main queue, the processing involves db-access, which is async and a http request, which is also async, and if it fails it writes to the retry queue, which is also async. So I am hoping the fact that all the operations are async means that the two queueClients injected at the top level will just be constantly asking for threads from the same thread pool? – ChrisCa Sep 04 '19 at 11:15
  • is there something I could do to prioritise processing on the main queue? – ChrisCa Sep 04 '19 at 11:15
  • Guess what I said probably sounded like “just get two thread pools”. If it did that way, than I should put it in another words. Problem with one thread pools is that there are IO threads and worker threads. [More info here](https://stackoverflow.com/questions/2099947/simple-description-of-worker-and-i-o-threads-in-net?lq=1). If you have a lot of IO work (in your case DB access and http request), there is a chance that such work will be throttled at some point because of IO threads exhaustion, so you won't get async callback continue processing fast. – cassandrad Sep 04 '19 at 12:24
  • What you have to do is to try to leave IO thread as soon as possible, that means that continuation after IO operation (DB/http) should work very small amount of time, probably queuing some work on worker thread by simply running a new task. But that matters only if you have thousands of new items in queue per sec. You have to monitor thread pool and your application time to time to notice thread pool starvation if amount of threads does not grow any more and processing time of incoming messages grows. If processing of new items from queues goes one at a time, you will be fine in any case. – cassandrad Sep 04 '19 at 12:28