This is a post, describing an issue we recently had on the Azure Service Bus.
Situation description
When a single appdomain is opening two (or more) service bus relay endpoints that have the same path (what is added after the servicebus.windows.net), but have a different namespace, the following exception is raised:
System.InvalidOperationException: The ChannelDispatcher at 'sb://repro2.servicebus.windows.net/ordersvc' with contract(s) 'ICustomerService' is unable to open its IChannelListener. ---> System.InvalidOperationException: A registration already exists for URI 'sb://repro2.servicebus.windows.net/ordersvc'.
The following is the configuration of my endpoints (not including the TokenProvider, etc, just the endpoints.
<endpoint address="http://repro1.servicebus.windows.net/ordersvc"
binding="basicHttpRelayBinding"
bindingConfiguration="httpRelayBinding"
contract="Demo1.Relay.ICustomerService"
behaviorConfiguration="repro1Behavior" />
<endpoint address="http://repro2.servicebus.windows.net/ordersvc"
binding="basicHttpRelayBinding"
bindingConfiguration="httpRelayBinding"
contract="Demo1.Relay.ICustomerService"
behaviorConfiguration="repro2Behavior" />
Why do we need the same services exposed on different namespaces?
Environment seperation
For Codit Integration Cloud, our azure-based integration platform, we are consuming some on-premises web services, exposed over the Azure Service Bus relay binding. We do this for different services that make part of our runtime. We also have a deployment cycle where we have different environments (a development, a test, a demo and off course the production environment(s)).
To isolate services, we make sure that every environment has a specific service bus namespace. This allows for security segregation and to move services on premises, without touching other environments. So this means that for our EdiFactParser service, we have the following endpoints (different names are being used here):
- sb://intcloud-dev.servicebus.windows.net/onprem/parse
- sb://intcloud-test.servicebus.windows.net/onprem/parse
- sb://intcloud-demo.servicebus.windows.net/onprem/parse
- sb://intcloud-prod.servicebus.windows.net/onprem/parse
As you can see the only difference in the above mentioned endpoints are the service bus namespaces. As mentioned, these services are hosted on different servers on premises, but in some cases, we host them together. (for example: dev & test are sharing the same local server). In our cases, these services are hosted in BizTalk Server receive locations.
Disaster recovery
In the rare case where an Azure center would be out of the air, all service bus namespaces (hosted in that data center) are unavailable. (There might be something like service bus federation in the future, but that’s not there yet). To make sure that our on premises services are still available, we could expose these services on multiple service bus namespaces. (hosted in different data centers).
In the case of a namespace being unavailable, the client that consumes the service could failover and try to consume the service over the second namespace.
How to work around this
This seems to be a bug in the Service Bus dll implementation, but we didn’t got a confirmation of this by product team yet. (there might be a good reason for this, allthough I don’t see it). Anyway, to workaround this, you need to open the different endpoints in separate service hosts. The following describes how to do this.
In BizTalk Server
We initially had the issue on BizTalk Server, where we expose these services over the service bus. Both receive locations were hosted in the same BizTalk host. Just moving both locations to a different BizTalk host, solved the problem.
In regular .NET applications
If you open the service host yourself, it as easy as creating two instances of the ServiceHost class and have them opening the endpoints seperately.
Just wanted to share this one
Sam Vanhoutte
9bae0d90-6fdd-4d39-8447-48482ccad7f5|1|5.0