0
votes

Im having a bit of trouble figuring out how to do the following correctly with the Distributor:

  1. Create a service (distributor) which sends commands, that are distributed among workers. If I start a Distributor with IWantToRunAtStartup implementation I can achieve this behaviour. See below.
  2. Create a service (worker) which handles these commands. This worker I would then start X number of instances of to scale out.
  3. This is all on the same machine so far.

The samples which are included with NSB are a bit hard to understand or maybe its just me :).

Example, I have a distributor and a worker:

Distributor:

class MessageCreator: IWantToRunAtStartup
{
    public IBus Bus { get; set; }

    public void Run()
    {
        Thread.Sleep(5000); //Allow workers to checkin
        for (int i = 0; i < 1000; i++ )
        {
            Bus.Send(new DoWorkForCustomerCommand { CustomerID = i });
        }

    }

    public void Stop() { }
}

...

public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
{
    public void Init()
    {
        Configure.Instance.RunDistributor();
    }
}

app.config

<configSections>
    <section name="Logging" type="NServiceBus.Config.Logging, NServiceBus.Core" />
    <section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" /> 
    <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
</configSections>

<MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
<Logging Threshold="INFO" />
<UnicastBusConfig>
    <MessageEndpointMappings>
      <add Messages="Messages" Endpoint="Worker" />
    </MessageEndpointMappings>
 </UnicastBusConfig>

Worker:

public class MessageHandler: IHandleMessages<DoWorkForCustomerCommand >
{
    public void Handle(DoWorkForCustomerCommand message)
    {
        Console.WriteLine("Handled customer with Id: " + message.CustomerID );
    }
}

...

public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher
{
    public void Init()
    {
        Configure.Instance.EnlistWithDistributor();
        // For some reason this: Configure.Instance.RunDistributor(); achieves the same thing.
    }
}

app.config

<configSections>
    <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
</configSections>
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error" />

This works on my machine and distributes nicely to any number of workers I start, but am i not missing out on something, the ScaleOut example seems more complex?

And why can i start the worker as a distributor and then see the worker act as if it was a worker when in fact is was started as a distributor?

Will this not work across machines if I just add a queue name/endpoint in the worker app.config?

1

1 Answers

1
votes

By default if you RunDistributor(), then NSB will run a Distributor with a Worker node in the same process. This is why you see a Worker despite the RunDistributor() configuration. To disable this, use RunDistributorWithNoWorkerOnItsEndpoint() instead. All of this will work across machines by changing the config.

I might suggest using the Profiles instead as this simplifies the config a bit. You can use the NServiceBus.Distributor and NServicerBus.Worker profiles. The profiles will give you more diagnostic information if you have not configured things quite right. Hope this helps.