【问题标题】:Multiple instances of a self hosted WCF service自托管 WCF 服务的多个实例
【发布时间】:2012-09-06 21:16:14
【问题描述】:

我们有一个从 C# 控制台应用程序运行的“worker”服务,对于开发,我们总是运行该服务的单个实例,它获取数据块并执行一些计算,这些数据块由另一个服务提供(它会跟踪剩余的数据量等)

现在在 QA 中,我们希望同时(在同一台机器上)运行多个“worker”服务实例。但是,一旦启动第二个实例,我们就会遇到异常:

TransportManager 未能使用 NetTcpPortSharing 服务:URI 已注册到 服务。

我们正在使用 netTcpBinding 并且端点地址被硬编码到 app.config 中并且保持不变,因此我假设我们遇到了这个错误。

<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> 

应用代码:

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

我们如何为每个实例提供不同的 URI,以便至少端口保持不变?

或者如果有不同的方式来运行同一服务的多个实例?

【问题讨论】:

  • 为什么要运行同一个服务的多个实例,是性能需求吗?
  • 是的,主服务“分配”工作(内部划分工作并跟踪下一批),工作服务实际执行工作。所以多个工人服务会减少我们的工作时间。
  • 为了您分配和划分工作的需要您可以使用中间路由服务查看 WCF 中的负载平衡 - robbincremers.me/2012/01/05/…
  • 好吧,分配部分不是这里的问题,即使我使用路由机制,我仍然需要打开多个(工作服务)实例来路由,这意味着打开多个端口。

标签: c# .net wcf multiple-instances self-hosting


【解决方案1】:

你可以定义你的specific behavior

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall, 
                 ConcurrencyMode = ConcurrencyMode.Multiple)]

【讨论】:

    【解决方案2】:

    如果您想拥有多个 service 实例,那么拥有单个服务主机就足够了 - 只需使用 ServiceBehaviorAttribute 装饰您的 WorkerService

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

    这将确保对服务的每次调用都会首先创建服务的新实例。其他创建服务类的方法可以找到here

    但是,如果您希望拥有多个服务主机,那么不可能有两个服务主机在完全相同的 url 上托管相同的服务。

    另一种情况是,如果您希望一个服务主机在具有相同基地址和自定义 uri 的多个端点上托管相同的服务。在这种情况下,您可以使用重载的 ServiceHost 构造函数或研究方法 AddBaseAddressAddServiceEndpoint。或者,如果您想从配置文件中执行此操作,而不是这里的简单示例,您的代码稍作修改

    <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>
    

    使用此配置,您将拥有两个服务端点

    net.tcp://localhost:8001/WorkerAssignment

    net.tcp://localhost:8001/QAWorkerAssignment

    【讨论】:

    • 我的服务已经用:[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class AssignmentService : IWorkerService 我得到了异常: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. 我想要实现的是让 Worker 服务运行两次,我不认为有两个不同的端点地址可以解决问题?
    • 当您在同一地址上启动多个服务主机时会出现此异常,这是预期的。在这种情况下,一台主机中的不同端点将解决该问题。
    • 但是如果你只启动一个主机,你可以在控制台netstat -aon 中使用以下命令检查是否已经有另一个应用程序在此端口上侦听
    【解决方案3】:

    Murtaza 你是对的,你仍然需要多个实例,问题是如何提供不同的端口

    备选方案 1: 对于每个服务实例:在调用 ServiceHost.Open 之前,您可以将端点添加到服务

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

    在上面的代码中,每个服务实例的地址部分可以有不同的端口。

    详情请关注link

    备选方案 2:启用端口共享

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <bindings>
          <netTcpBinding>
            <binding portSharingEnabled="true">
              <security mode="None" />
            </binding>
          </netTcpBinding>
        </bindings>
      </system.serviceModel>
    </configuration>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-29
      相关资源
      最近更新 更多