nServiceBus NServiceBus training - opens a new tab
 
  Overview Documentation Downloads Community Roadmap License
 

Publish/Subscribe Configuration

Pub/Sub configuration

The part of the <add> entry stating Messages="Messages" means that the assembly "Messages.dll" contains the message schema.

Specific types can be configured by using their qualified name:
"namespace.type, assembly".

The part stating Endpoint="messagebus" is telling the subscriber's bus object that the publisher will be accepting subscription requests on that queue.

The queue name "messagebus" is short for "the queue named 'messagebus' on the local machine". To indicate a queue on a remote machine, you use a format similar to email: MessageBus@RemoteServer.


The input queue of each process does need to be on the same machine as the process though.


At this point, the bus in the subscriber process knows about the message schema and the endpoint on which the publisher is willing to accept subscription requests. The bus object then sees that there is applicative code in the subscriber that wants to handle those messages, and therefore sends a subscription request to that endpoint.

Subscription Intent

The way that applicative code in the subscriber handles the messages published by the publisher is by implementing one of the NServiceBus interfaces (IHandleMessages<T>) as shown below:

Handling messages

This interface requires the single 'Handle' method accepting a parameter of the same type as declared in the class inheritance. We can ignore the body of the method for now as it has no bearing on how the publish/subscribe works.

Since the message being handled (EventMessage) belongs to the message assembly previously described (Messages.dll), and the subscriber's bus knows those messages belong to the publisher (from the app.config above), and the only way that a process can handle messages belonging to someone else is for them to be a subscriber, the bus automatically subscribes.

Here's how it works...

Messaging Mechanics

Subscribing

The way that the bus at the subscriber subscribes to the publisher is by sending a message to the queue that has been configured in its <UnicastBusConfig> section as described above.

In this message, the bus includes the type of message and the input queue of the subscriber. When the bus at the publisher side receives this message, it stores the information.

It is important to understand that each publisher is responsible for its own information. There isn't necessarily some logically central broker which stores everything, although NServiceBus does allow for configuring all publishers to store their information in a physically central location, such as a database.

There's also nothing that stops a subscriber from also being a publisher. Here's how simple it is to state that a given process is a publisher:

How to be a Publisher

In order to indicate that a given process is a publisher, all you need to do is reference the NServiceBus assemblies and write a class which implements IConfigureThisEndpoint and AsA_Publisher as shown below.

On top of the 3 NServiceBus assemblies referenced, it's also important to reference 'log4net' which is the open-source library that is used for logging. Logging is configured in NServiceBus slightly different than the standard log4net model - for more information click here.

Setting up a publisher

We can ignore the interface ISpecifyMessageHandlerOrdering for now.

Subscription Storage

NServiceBus internally sets up the storage where subscription information will be placed. By default, NServiceBus stores this information in memory but there are also built in storage options on top of MSMQ and databases. You don't need to specify this yourself either in code or config - see how profiles work in NServiceBus for more information here.

In order to configure MSMQ as your subscription storage, call ".MsmqSubscriptionStorage()" in the code after "NServiceBus.Configure.With().Log4Net().DefaultBuilder()". You don't need any configuration changes for this to work - NServiceBus will automatically use a queue called "NServiceBus_Subscriptions". If you want control over the queue used to store the subscriptions, add the following config section and subsequent config entry:


<section name="MsmqSubscriptionStorageConfig"
         type="NServiceBus.Config.MsmqSubscriptionStorageConfig, NServiceBus.Core" />

<MsmqSubscriptionStorageConfig Queue="YourQueue" />


If you want multiple machines to share the same subscription storage, do not use the MSMQ option outlined above - instead use the database-backed stored described here.

In order to configure a database as your subscription storage, call ".DBSubcriptionStorage()" in the code after "NServiceBus.Configure.With().Log4Net().DefaultBuilder()". This option requires the following to be present in your config:


<section name="DBSubscriptionStorageConfig"
         type="NServiceBus.Config.DBSubscriptionStorageConfig, NServiceBus.Core" />

<DBSubscriptionStorageConfig>
  <NHibernateProperties>
    <add Key="connection.provider" 
         Value="NHibernate.Connection.DriverConnectionProvider"/>
    <add Key="connection.driver_class" 
         Value="NHibernate.Driver.SqlClientDriver"/>
    <add Key="connection.connection_string" 
         Value="Server=YOUR_DB_SERVER;initial catalog=NServiceBus;Integrated Security=SSPI"/>
    <add Key="dialect" 
         Value="NHibernate.Dialect.MsSql2005Dialect"/>
  </NHibernateProperties>
</DBSubscriptionStorageConfig>

If you don't want all of this information in your config, you can specify it in code through the overload of the DBSubscriptionStorage method which accepts a dictionary of the NHibernate properties above.

The additional 'autoUpdateSchema' parameter, if set to 'true' tells NServiceBus to create the necessary tables in the configured database to store the subscription information. This table is called 'Subscriptions' and has two columns, 'SubscriberEndpoint' and 'MessageType' - both of them varchars.

For more information on NHibernate configuration see this page, specifically Table 3.1 and the optional configuration options in section 3.5. Table 3.3 will help you configure other databases like Oracle and MySQL.

How to publish

In order to publish a message, you need a reference to the bus object in your code. In the pub/sub sample, this code is in the ServerEndpoint class in the Server project as shown below:

Server Endpoint

The 'Bus' property is automatically filled by the infrastructure. This is known as 'Dependency Injection'. All development done with NServiceBus makes use of these patterns so if you aren't very familiar with this style of development, please read more about it here (opens a new window). The technology used as the dependency injection container by NServiceBus is pluggable, with 5 options available out of the box - Spring is the default.

In the 'Run' method, you'll see the creation of the event message. This can be as simple as instantiating the relevant class or using the bus object to instantiate messages defined as interfaces. For more information on whether to use interfaces or classes to represent messages, see here.

Once the event message object has been created, the call to Bus.Publish(eventMessage); tells the bus object to have the given message sent to all subscribers who had expressed interest in that type of message. As we saw in the walkthrough, if a subscriber is unavailable, their messages aren't lost - they're stored until the subscriber comes back online. See the 'store and forward messaging' section of the architectural principles of NServiceBus for more information.

Security & Authorizations

You may not want to allow any endpoints to subscribe to a given publisher or event. NServiceBus provides a way for you to intervene in the subscription process and decide whether a given client should be allowed to subscribe to a given message. You can see this in the SubscriptionAuthorizer class in the Server project.

Notice that the class implements the IAuthorizeSubscriptions interface, which requires the methods AuthorizeSubscribe and AuthorizeUnsubscribe. The implementation that comes in the sample doesn't do very much - returning true in both. In a real project, you may access some Access Control System, Active Directory, or maybe just a database to decide if the action should be allowed.


As you can see, there is a lot going on under the covers. NServiceBus provides you full control over every part of the message exchange all the while abstracting the underlying technologies. Try modifying the sample a bit, adding your own message handlers, and debugging through the various pieces to get a better feeling for what's going on.

Next Steps

If you have questions about why things work a certain way,
or how best to use NServiceBus on your project,
the best place to go is the discussion group.

Join over 400 developers like you discussing what problems NServiceBus solves for them.
Listen in on architectural discussions about highly available deployments.
Get advice from people who've been working with it for years.
And we'll never (ever) share your email adress with anyone else.

Signing up is quick and easy:
Click to join

If you don't feel like signing up right now, that's OK too.
How about taking a look at the other samples that come with NServiceBus?

Continue to the samples.





NServiceBus is managed and run by Udi Dahan.
Committers include Andreas Öhlund and Matt Burton.

All content on this site is licensed under the Creative Commons Attribution License.