Unhappy with subscription process in NSB v7 beta

(David Rettberg) #1

I don’t have time to write everything up, so I’m asking you to trust me when I say auto-subscribe is not an option for our projects.

I am working on upgrading our code from NSB v5 and v6 to v7 to test whether we will be able to migrate completely to .NetStandard 2.0. Here are the relevant PackageReference entries from our .csproj:

<PackageReference Include="Ninject" Version="3.3.4" />
<PackageReference Include="NServiceBus.Newtonsoft.Json" Version="2.0.0-beta0002" />
<PackageReference Include="NServiceBus.Ninject" Version="7.0.0-beta0003" />
<PackageReference Include="NServiceBus.Persistence.Sql" Version="4.0.0-beta0002" />
<PackageReference Include="NServiceBus.SqlServer" Version="4.0.0-beta0004" />

Our apps consist of multiple Windows services, all of which subscribe to some events and publish other events. In both our v5 and v6 based apps, we write our “MessageEndpointMappings” config entries such that the Endpoint attribute for each event is the current service’s queue, since that is the only queue that is guaranteed to be configured when we call subscribe for that event. This worked great because the subscriber code didn’t have to be updated whenever another service publishes an existing event. It worked because all the subscription information was written to a single Subscription table shared by all the services associated with that bus.

From what I’ve seen so far in v7, each service gets it’s own subscription table, so the subscriber now must know all the publishers of the events it cares about. Additionally, a subscription command must be processed by each logical publisher before that publisher can notify the subscriber. This means an unknown number of other messages will need to be processed by the publishers before they even see the subscription command, leading to subscribers missing any events that were published after the subscriber sent the subscription command but before that event’s publisher processed the subscription command.

Can someone explain why the Subscription table was split? I’m assuming it was done with good intentions, but ,on my own, I can’t think of any benefit to the new pattern.

(Szymon Pobiega) #2

Hi David

The behavior you see is not new to V7. This is the default way SQL persistence works: it prefixes all its tables with the name of the endpoint. The short story is you can override it by via TablePrefix method and provide a prefix yourself. It can be an empty string.

The longer story is following…

The way you are using the MessageEndpointMappings is not the way it was originally intended to be used. The Endpoint was supposed to point to the actual publisher because each publisher can use a different persistence mechanism. That said, we know there are issues with the order the endpoints start up etc that’s why we generally discourage using auto-subscribe in production. The alternative is to use auto-subscribe in test environments and capture the subscription store information in form of a script that can be executed against the production database to set the subscriptions up prior to actually starting the endpoints.

What you’ve build by using self as the publisher endpoint is a form of native publish/subscribe mechanism for the SQL Server transport. This is something we have on our radar for some time https://github.com/Particular/NServiceBus.SqlServer/issues/373. Unfortunately we haven’t started working on it yet. I understand your point of view. It just makes sense that, when using a single shared SQL instance, the subscriptions are managed by the transport and not the persistence.

Another thing you might want to look at is the File-based Routing. We’ll be upgrading it to V7 soon. It uses a shared file to set up the routing for both events and commands.

Bottom line is, in order to be sure that a fresh new subscribe does not miss any events, you need to make sure that the act of subscribing is carried out as part of the deployment procedure, not as part of the start-up of the endpoint. This means that auto-subscribe is dangerous in production environments. Take a look at the SQL persistence deployment workflow and consider adding the subscribe scripts to the version control alongside the endpoint. Then execute both the schema creation and the subscribe scripts before the endpoint is deployed and started.

Hope it helps,

(David Rettberg) #3

@SzymonPobiega, thanks for your quick reply. I was abler to use the tip about the TabelPrefix to quickly restore the behavior I was expecting. For a longer term solution, I am leaning towards the file-dased router system about which you reminded me.