简体   繁体   中英

Implementing a A Publish-Subscribe Channel using NServiceBus

I am trying to implement a Publish-Subscribe Channel using NServiceBus. According to the Enterprise Integration Patterns book, a Pulish-Subscribe Channel is described as:

A Publish-Subscribe Channel works like this: It has one input channel that splits into multiple output channels, one for each subscriber. When an event is published into the channel, the Publish-Subscribe Channel delivers a copy of the message to each of the output channels. Each output end of the channel has only one subscriber, which is allowed to consume a message only once. In this way, each subscriber gets the message only once, and consumed copies disappear from their channels.

Hohpe, Gregor; Woolf, Bobby (2012-03-09). Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions (Addison-Wesley Signature Series (Fowler)) (Kindle Locations 2880-2883). Pearson Education. Kindle Edition.”

There is a sample containing a publisher and subscriber at: http://docs.particular.net/samples/step-by-step/ . I have built the sample solution for version 5. I then ran multiple subscribers in different command line windows to see how the system behaves.

Only one subscriber receives the event that is published, even though there are multiple subscribers. Publishing multiple events causes at most one subscriber to handle the event.

I cannot find any information about how to configure NServiceBus as a Publish-Subscribe Channel as defined in the quoted text. Does anyone know how to do this? Is this not supported?

[Update 2 Feb 2016]

I did not rename my endpoints after copying the subscribers. That gave me the desired behaviour.

If you are running multiple instances of the same subscriber, then what you are describing is the intended functionality.

Scenarios

1 Publisher, 1 Logical Subscriber

在此处输入图片说明

Some processor publishes an event and an email handler is subscribed to that event. When the event is consumed by the email handler, the email handler will send an email. In this scenario, there is only one logical subscriber, the email handler. Therefore, only one copy of the event is sent.

1 Publisher, 2 Logical Subscriber

在此处输入图片说明

In the next scenario, there are two logical subscribers: the invoice Handler and the email handler. When processor publishes an event, two copies of the event are sent. One to the invoice handler and one to the email handler.

1 Publisher, 2 Instances of 1 Logical Subscriber

在此处输入图片说明

In this scenario, there is only one logical subscriber even though there are two services subscribed to the event. In this case, only one copy of the event is sent and only one of the email handlers will process the event. If both email handlers processed the event then you would have N operations done for N number of instances of a subscriber. In other words, two emails would be sent instead of just one. Most likely, this scenario needed two email handlers because a single handler couldn't keep up with the load of the processor, or, was required for redundancy.

Summary

If you simply spin up multiple instances of the same subscriber, you will still only have one subscriber handle that event. This is by design. Otherwise, the work would be duplicated for every additional process.

If you want to see two logical subscriber, create a new project within that solution, with a different name, and subscribe to the same event (either in code or with config files). Then launch the publisher and one instance of each subscriber. Once the publisher publishes an event, you'll see both subscribers process the event.

The subscribers need to start up first to be able to send the message that they're interested in subscribing to an event. Then the publisher needs to boot up, have the time to process the subscription messages. When all subscriptions are stored, only then can you publish messages. If you publish messages before all subscriptions are actually stored, NServiceBus will only send the message to the subscribers it already knows about. A second later all subscribers might be known, but by then you've already published your message.

When using durable persistence, like SQL Server or something like it, the subscriptions will be stored and kept. So after restarting the service, immediately all subscribers are known. With in-memory storage, the subscriptions are lost every single time your publisher is restarted. So the need to wait a bit until all subscriptions are processes, is longer.

It can also be a problem that not every subscriber is actually sending out a message, because you might've gotten the configuration wrong.

I've written a tutorial myself which might help out as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM