Im having a bit of trouble figuring out how to do the following correctly with the Distributor:
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.
Create a service (worker) which handles these commands. This worker I would then start X number of instances of to scale out.
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?
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.
Related
I have a speciifc configuration problem.
<configuration>
<configSections>
<section name="custom" type="ConfigurationSample.CustomConfigurationSection, ConfigurationSample"/>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<custom>
<customConfigurations>
<configuration id="CAT1">
<name>Tom</name>
<address type="rent">
<area>Misissipi</area>
</address>
<conifugration/>
<configuration id="Mouse1">
<name>Jerry</name>
<address type="own">
<area>Seatle</area>
</address>
<conifugration/>
<customConfigurations>
</custom>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IAnimal" type="MyApp.IAnimal, MyApp" />
<alias alias="CAT" type="MyApp.CAT, MyApp" />
<alias alias="Mouse" type="MyApp.Mouse, MyApp" />
<container>
<!-- should register CAT instance with name CAT1 at runtime and mapto IAnimal !-->
<!-- should register Mouse with name Mouse1 at runtime and mapto IAnimal !-->
</container>
</unity>
</configuration>
This is my app.config. All I am looking for runtime registering instances in unity container while reading the custom config section since CAT class CAT configuration in its constructor.
My classes:
public interface IAnimal
{
public string Name {get;set}
pubic bool IsLiving();
}
public class Mouse
{
MouseConfig config;
public Mouse(IAnimalConfig config)
{
this.config=config;
}
public string Name {get;set}
pubic bool IsLiving(){
//do something with config
}
}
public class Cat
{
CATConfig config;
public CAT(IAnimalConfig config)
{
this.config=config;
}
public string Name {get;set}
pubic bool IsLiving(){
//do something with config
}
}
I hope you understand where i am leading to. I need to provide config objects as parameter to the derived classes. So based on my customconfig i want to register instances in unity container. So i can work with those instances in my application. since i already know their types and name of those instances i can resolve from container.
Please let me know if i have to add anything more. Thanks
Spent more than 4 hours trying to figure out why etw logs wont show up in my tables. I still am unable to figure out why my logs are not showing up in azure table.
EDIT
The service is hosted as cloud service.
Here is how my diagnostics xml looks like. This is auto generated by selecting options in visual studio
<?xml version="1.0" encoding="utf-8"?>
<DiagnosticsConfiguration xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration">
<PublicConfig xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration">
<WadCfg>
<DiagnosticMonitorConfiguration overallQuotaInMB="4096">
<EtwProviders>
<EtwEventSourceProviderConfiguration provider="AzureEventSource">
<Event id="1" eventDestination="Error" />
<Event id="2" eventDestination="Warning" />
<Event id="3" eventDestination="Debug" />
<Event id="4" eventDestination="Performance" />
<DefaultEvents eventDestination="Default" />
</EtwEventSourceProviderConfiguration>
</EtwProviders>
<Logs scheduledTransferPeriod="PT2M" />
</DiagnosticMonitorConfiguration>
</WadCfg>
<StorageAccount />
</PublicConfig>
<PrivateConfig xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration">
<StorageAccount endpoint="" />
</PrivateConfig>
<IsEnabled>true</IsEnabled>
</DiagnosticsConfiguration>
This is how my class looks like
using Microsoft.Diagnostics.Tracing;
namespace CommonUtils
internal sealed class AzureEventSource : EventSource, ILogger
{
public AzureEventSource(Type owner) : base(owner.FullName)
{
}
private bool IsInputInvalid(String message)
{
return String.IsNullOrWhiteSpace(message);
}
public void Error(string message, params object[] args)
{
if (IsInputInvalid(message))
{
throw new ArgumentNullException("message");
}
this.WriteEvent(1, string.Format(message, args));
}
}
}
I am pretty sure I am missing something simple.
Any help will be greatly appreciated
Assuming you're referring to Microsoft.Diagnostics.Tracing.EventSource in your above example.
You're missing EventSource Event attributes for your class and method respectively.
A simple hello world of eventsource looks like this.
[EventSource(Name = "HelloEventSource")]
internal sealed class HelloEventSource : EventSource
{
[Event(1, Level = EventLevel.Informational, Message = "Hello World! {0}")]
public void HelloWorld(string name)
{
WriteEvent(1, name);
}
}
You should fix the tracing part of your code and check the logs are getting generated locally on your machine/vm.
Sending the events via diagnostics pipeline of your choice comes next.
I have a simple structure of classes, interfaces as follows:
public interface IMessagingClient (interface supporting service bus queue operation)
public class ServiceBusMessagingClient : IMessagingClient (real implementation)
public class MockMessagingClient : IMessagingClient (mock implementation for our unit test)
public class FailoverMessagingClient : IMessagingClient (this implementation internally uses 2 clients and switches roles b/w 2 as and when disaster in a datacenter occur)
{
private IMessagingClient PrimaryClient { get; set; }
private IMessagingClient SecondaryClient { get; set; }
}
We load unity config from web.config/app.config and use it in our product code and test code.
We want following:
For production scenario, PrimaryClient and SecondaryClient should of type ServiceBusMessagingClient
For Test scenario, PrimaryClient and SecondaryClient should of type MockMessagingClient
Our current unity config looks like:
<container name="azure">
<register type="IMessagingClient" mapTo="FailoverMessagingClient"/>
</container>
Do we have to use some interceptors to achieve this? Or by defining a ctor in FailoverMessagingClient and using ctor injection?
Some suggestions would be great!
You can do this using named registrations.
For example, given the following example set up:
namespace ConsoleApplication8
{
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
public interface IMessagingClient { }
public class ServiceBusMessagingClient : IMessagingClient { }
public class MockMessagingClient : IMessagingClient { }
public class FailoverMessagingClient : IMessagingClient
{
private readonly IMessagingClient primaryClient;
private readonly IMessagingClient secondaryClient;
public FailoverMessagingClient(IMessagingClient primaryClient, IMessagingClient secondaryClient)
{
this.primaryClient = primaryClient;
this.secondaryClient = secondaryClient;
}
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer().LoadConfiguration();
var failOverMessagingClient = container.Resolve<IMessagingClient>("Two");
}
}
}
you can hook up the dependencies using the app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IMessagingClient" type="ConsoleApplication8.IMessagingClient, ConsoleApplication8" />
<alias alias="ServiceBusMessagingClient" type="ConsoleApplication8.ServiceBusMessagingClient, ConsoleApplication8" />
<alias alias="MockMessagingClient" type="ConsoleApplication8.MockMessagingClient, ConsoleApplication8" />
<alias alias="FailoverMessagingClient" type="ConsoleApplication8.FailoverMessagingClient, ConsoleApplication8" />
<container>
<register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" />
<register type="IMessagingClient" name="Two" mapTo="FailoverMessagingClient">
<constructor>
<param name="primaryClient">
<dependency type="IMessagingClient" name="One" />
</param>
<param name="secondaryClient">
<dependency type="IMessagingClient" name="One" />
</param>
</constructor>
</register>
</container>
</unity>
</configuration>
Changing the line
<register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" />
to
<register type="IMessagingClient" name="One" mapTo="MockMessagingClient" />
will allow you to swap out your implementation of IMessagingClient as appropriate.
Personally, I would rather do this using the fluid syntax
var container = new UnityContainer();
container.RegisterType<IMessagingClient, ServiceBusMessagingClient>("One");
container.RegisterType<IMessagingClient, FailoverMessagingClient>("Two",
new InjectionConstructor(new ResolvedParameter<IMessagingClient>("One"), new ResolvedParameter<IMessagingClient>("One")));
var failOverMessagingClient = container.Resolve<IMessagingClient>("Two");
When using the unity container, you can override an existing registration by registering it again for a different class.
For example:
If you run this code:
container.RegisterType<IMessagingClient, ServiceBusMessagingClient>();
container.RegisterType<IMessagingClient, MockMessagingClient>();
The first registration is overridden and so IMessagingClient is mapped to MockMessagingClient. Its like the first line never executed.
You can use this fact, and in your unit test (in the arrange phase or in the setup method of your test class), simply register the IMessagingClient to the mock implementation like this (after loading the XML configuration):
container.RegisterType<IMessagingClient, MockMessagingClient>();
By the way, you might not want to use DI containers in unit tests. Take a look at this question.
I am admittedly going a little bit crazy on the subject, so bear with me. I've been attempting to do this for about 5 hours now, and I'm pretty much just banging my head against the wall at this point. Here is what I have:
Global.asax.cs
namespace MyApp
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
Database.SetInitializer(new MyInitializer());
}
}
}
MyInitializer.cs
namespace MyApp.App_Start
{
public class MyInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{
protected override void Seed(MyContext context)
{
// seed data goes here
sample_data = new List<MyModel>
{
new MyModel{"foo"},
new MyModel{"bar"}
};
sample_data.ForEach(s => context.MyModels.Add(s));
context.SaveChanges();
}
}
}
MyContext.cs
namespace MyApp.Models
{
public class MyContext : DbContext
{
public MyContext() : base("MyContext")
{
Database.SetInitializer<MyContext>(new MyInitializer());
}
public DbSet<MyModel> MyModels { get; set; }
}
}
Web.config
<connectionStrings>
<add name="MyContext" connectionString="Data Source=(localdb)\v11.0; Initial Catalog=MyContext; Integrated Security=True; MultipleActiveResultSets=True; AttachDbFilename=|DataDirectory|MyContext.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<contexts>
<context type="MyApp.Models.MyContext, MyApp">
<databaseInitializer type="MyApp.App_Start.MyInitializer, MyApp" />
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
I just cannot figure out why it's not seeding any of the data. I've read through the dozen or more similar cases here and elsewhere, tried just about every iteration, and still can't get it to trigger at all. It never even hits the Seed() function. The database exists, and if I remove it, it is rebuilt, but never populated.
I'm leaning towards there being a problem with my web.config, but I haven't figured it out yet. Any suggestions?
According to this blog, the DbInitializer isn't called until you actually try to access the database.
// Code copied from linked blog
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<BlogContext>());
using (var db = new BlogContext()) //initializer won't be called here
{
...
db.Categories.Add(cat); //initializer will be called here
db.BlogPosts.Add(post);
...
}
Console.ReadLine();
}
I resolved this. Apparently, the issue was two-fold.
The "DropCreateDatabaseIfModelChanges" in the initializer wasn't firing, as it didn't see that the model had changed. Changing this to "DropCreateDatabaseAlways" worked, but would usually result in a "Cannot drop database because it is currently in use" error message. A manual disconnect of databases and restart of VS usually resolved this, though I still usually had to run it 2-3 times. Once it dropped and rebuilt the database, reverting to "DropCreateDatabaseIfModelChanges" is faster and still works.
I may have been missing a line in my Web.config
<appSettings>
<add key="MyInitializer MyApp.Models.MyContext, MyApp.Models" value="MyApp.App_Start.MyInitializer, MyApp.Models" />
</appSettings>
Between these two things [well, more like 4 things], it seems to work now.
I want use NServiceBus with GetEventStore to create CQRS/EventSourcing solution.
I have a set of Events each is stamped with Aggregate type name and Aggregate id. My domain publishes events using NServiceBus. All events derive from one base type.
I want create message handler which subscribes to all events published by domain, so it can save events in EventStore.
I tried subscribe to my base Event but it doesn't work.
Is there any way to subscribe to all types of events? I don't also want to change NServiceBus configuration or add new handler in my EventStore worker each time I create new domain Event.
I've managed to solve the problem. I have a base Event class and I publish events that derive from the base Event class. On my subscriber I subscribe to base Event and Handle method is firing every time derived event is published.
Messages project
public class Event : IEvent
{
}
public class Event1 : Event
{
}
public class Event2 : Event
{
}
Publisher project
Publishers EndpointConfig
namespace SemplePublisherNamespace
{
using NServiceBus;
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher
{
}
}
Publishers OnBusStart class
public class OnBusStart : IWantToRunWhenBusStartsAndStops
{
public IBus Bus { get; set; }
void IWantToRunWhenBusStartsAndStops.Start()
{
Bus.Publish(new Event1());
Bus.Publish(new Event2());
}
void IWantToRunWhenBusStartsAndStops.Stop()
{
}
}
Publishers app.config
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<configuration>
<configSections>
<section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
<section name="AuditConfig" type="NServiceBus.Config.AuditConfig, NServiceBus.Core"/>
</configSections>
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
<AuditConfig QueueName="audit" />
</configuration>
Subscriber project
Subscribers EndpointConfig
namespace SampleSubscriber
{
using NServiceBus;
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
{
}
}
Subscribers app.config
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<configuration>
<configSections>
<section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
<section name="AuditConfig" type="NServiceBus.Config.AuditConfig, NServiceBus.Core" />
</configSections>
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error" />
<UnicastBusConfig>
<MessageEndpointMappings>
<add Assembly="Messages" Endpoint="SemplePublisherNamespace" />
</MessageEndpointMappings>
</UnicastBusConfig>
<AuditConfig QueueName="audit" />
</configuration>
Note that in MessageEndpointMappings secion when adding mapping we set Endpoint name and it's the same as namespace of EndpontConfig class in Publisher project.
Subscriber's Handler class
public class Subscriber : IHandleMessages<Event>
{
public void Handle(Event message)
{
Console.WriteLine("Handle: "+message.GetType().Name);
}
}
Another possible approach would be to have your Event acting as a generic envelope with the actual content inside:
public class GenericEnvelope
{
...
public XmlElement Message { get; set; }
}
This still lets you subscribe once and then pass whatever the content you want but the advantage of such approach is that the envelope could possibly contain some message-oriented attributes that are not part of the message. Another advantage is that passing the content as XmlElement lets you implement your own message-level security/integrity (signing and/or encryption).