4

We have a "worker" service running from console application in c#, for development we were always running a single instance of this service, which fetches chunks of data and performs some calculations, these chunks of data are provided by another service (which keeps track of how much data is left etc.)

Now in QA we want to run multiple instances of the "worker" service simultaneously (on the same machine).However we are get an exception as soon as the second instance is launched:

The TransportManager failed to listen on the supplied URI using the NetTcpPortSharing service: the URI is already registered with the service.

We are using netTcpBinding and the endpoint address is hardcoded into the app.config and remains the same and because of that I assume we are getting this error.

<services>
    <service behaviorConfiguration="CoreBehavior" name="WorkerService">
        <endpoint address="net.tcp://localhost:8001/WorkerAssignment" binding="netTcpBinding" contract="IWorkerService" bindingConfiguration="CoreTcpBinding"/>
    </service>
</services>
<bindings>
    <netTcpBinding>
        <binding name="CoreTcpBinding" portSharingEnabled="true">
            <security mode="None"/>
        </binding>
    </netTcpBinding>
</bindings> 

Application code :

var host = new ServiceHost(typeof(WorkerService));
host.Open();

How do we provide a different URI for each instance so that atleast the port will remain the same ?

OR If there is a different way to run multiple instances of the same service?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Murtaza Mandvi
  • 10,708
  • 23
  • 74
  • 109
  • Why you want to run multiple instance of the same service, is it a performance need? – Milan Raval Sep 14 '12 at 08:21
  • Yes, the main service "assigns" work (which internally divides work and keeps track for next batch) and the worker service actually performs work. So multiple worker services would give us less working time. – Murtaza Mandvi Sep 20 '12 at 18:35
  • For your needs to assign and divide work You can check out the load balancing in WCF using intermediate routing service - http://robbincremers.me/2012/01/05/wcf-routing-and-load-balancing-based-on-message-content-with-routingservice-and-an-xpath-message-filter/ – Milan Raval Sep 20 '12 at 23:40
  • one more link - http://www.codeproject.com/Articles/260996/Router-Service-in-WCF-4-0 – Milan Raval Sep 20 '12 at 23:41
  • Well, the assigning part is not the issue here, even if I use the routing mechanism, I still would need multiple instances (of worker service) open to route to, which means opening multiple ports. – Murtaza Mandvi Sep 21 '12 at 15:32
  • very true Murtaza, refer my answer below – Milan Raval Sep 22 '12 at 03:31

3 Answers3

4

If you want to have multiple instances of the service than it is enough to have single service host - just decorate you WorkerService with ServiceBehaviorAttribute

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Percall)] 
public class WorkerService : IWorkerService 
{
  //...service data
}

This will make sure that every call to the service will first create new instance of the service. Other ways of creating service class can be found here

If, however you would like to have multiple service hosts than it is impossible to have two service hosts that will host same service on completely the same url.

Another case would be if you want to have one service host hosting the same service on multiple endpoints with the same base address and custom uri's. In this case you can make use of overloaded ServiceHost constructor or investigate methods AddBaseAddress , AddServiceEndpoint. Or if you want to do it from configuration file than here's simple example with your code slightly modified

<service behaviorConfiguration="CoreBehavior" name="WorkerService">
    <endpoint address="WorkerAssignment" binding="netTcpBinding" contract="IWorkerService"/>
    <endpoint address="QAWorkerAssignment" binding="netTcpBinding" contract="IWorkerService"/>
  <host>
    <baseAddresses>
      <add baseAddress="net.tcp://localhost:8001/" />
    </baseAddresses>
  </host>
</service>

with this configuration you will have two endpoints for your service

net.tcp://localhost:8001/WorkerAssignment

net.tcp://localhost:8001/QAWorkerAssignment

Community
  • 1
  • 1
tchrikch
  • 2,428
  • 1
  • 23
  • 43
  • my Service is already decorated with : `[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class AssignmentService : IWorkerService` I get the exception : `There is already a listener on IP endpoint 0.0.0.0:8001. Make sure that you are not trying to use this endpoint multiple times in your application and that there are no other applications listening on this endpoint.` What I am trying to achieve is have the Worker service run twice, I do not think having two different endpoint address solves the issue? – Murtaza Mandvi Sep 13 '12 at 19:33
  • You get this exception when you're starting more than one service host on the same address and this is expected. In this case different endpoints in one host will solve the issue. – tchrikch Sep 13 '12 at 19:36
  • But if you only start one host than you can check for example with the following command in the console `netstat -aon` if there is already another applicationi listenint on this port – tchrikch Sep 13 '12 at 19:37
1

Murtaza you are right that you still need multiple instances and the issue is how to give different port

Alternate 1: For each instance of service: before calling ServiceHost.Open you can add endpoint to the service

ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService))
WSHttpBinding binding = new WSHttpBinding();
serviceHost.AddServiceEndpoint(typeof(ICalculator), binding, "http://localhost:8000/servicemodelsamples/service/basic");

In above code the address part can have different port for each instance of the service.

For details following link

Alternate 2: Enable port sharing

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding portSharingEnabled="true">
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
  </system.serviceModel>
</configuration>
Milan Raval
  • 1,880
  • 1
  • 16
  • 33
0

You can define your specific behavior

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall, 
                 ConcurrencyMode = ConcurrencyMode.Multiple)]
Aghilas Yakoub
  • 28,516
  • 5
  • 46
  • 51