并行回调订阅者

时间:2013-02-11 04:23:40

标签: c# wcf .net-4.0 parallel-processing publish-subscribe

我有一个向订阅客户端发送数据的WCF服务。使用顺序循环,进程非常慢,因为循环中有3个循环,例如;

for (int x = 0 ; x <= MasterTables.count - 1 ;x ++)
{
    for (int y = 0; y <= MasterData[x].count ; y++)
    {
        foreach (SubList subscriber in subscribers.ToList())
        {
            SendDatatoSubscriber();
        }
    }
}

因此,我将顺序循环转为并行循环,这反过来要快得多,但不利的一面是服务器同时向单个订阅服务器发布多个回调,因此传输通道超时。

SendDatatoSubscriber()事件是同步调用,因为我需要客户端确认它已收到对象并向服务器返回特定消息,因为有更多事件依赖于此结果。

我的网络配置和客户端配置如下:

服务配置:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
    <authentication mode="None"/>
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="NetTcpSecure" closeTimeout="23:00:00" openTimeout="23:00:00" receiveTimeout="23:00:00" sendTimeout="23:00:00" transactionFlow="false" transferMode="Buffered" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="2000" maxReceivedMessageSize="2147483647" portSharingEnabled="true">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
          <reliableSession inactivityTimeout="23:00:00" enabled="false"/>
          <security mode="Message">
            <transport clientCredentialType="None">
              <extendedProtectionPolicy policyEnforcement="Never"/>
            </transport>
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="service.ClientBehavior" name=" service.DTSClient">
        <endpoint address="" behaviorConfiguration="WcfDts.DTSClientEndpointBehavior" binding="netTcpBinding" bindingConfiguration="NetTcpSecure" name="ClientNetTcp" contract="WcfDts.IDTSClient"/>
        <endpoint address="mex" binding="mexHttpBinding" behaviorConfiguration="WcfDts.DTSClientEndpointBehavior" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://127.0.0.1:8000/WcfDts/Services"/>
          </baseAddresses>
          <timeouts closeTimeout="23:00:00"/>
        </host>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name=" service.DTSClientEndpointBehavior">
          <wsdlExtensions location="http://127.0.0.1/ service /Services/DTSClient.svc" singleFile="True"/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name=" service.ClientBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType=" service.CustomUserNameValidator, service "/>
            <serviceCertificate findValue="CertName" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
            <clientCertificate>
              <certificate findValue=" CertName " storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
            </clientCertificate>
          </serviceCredentials>
          <serviceThrottling maxConcurrentCalls="2000" maxConcurrentInstances="2000" maxConcurrentSessions="2000"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <extensions>
      <behaviorExtensions>
        <add name="wsdlExtensions" type="WCFExtras.Wsdl.WsdlExtensionsConfig, WCFExtras, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </behaviorExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

客户端配置:

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="ClientNetTcp" closeTimeout="23:59:59" openTimeout="23:59:59" receiveTimeout="23:59:59" sendTimeout="23:59:59" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="100000" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="100000" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
          <reliableSession ordered="true" inactivityTimeout="23:59:59" enabled="false"/>
          <security mode="Message">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
            <message clientCredentialType="UserName" algorithmSuite="Default"/>
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://BaseAdress:Port/Services/Service.svc" binding="netTcpBinding" bindingConfiguration="ClientNetTcp" contract="Sub.IClient" name="ClientNetTcp">
        <identity>
          <dns value="CertName"/>
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

所以我的问题是:

  1. 我是否需要修改配置以控制超时情况
  2. 或者如何使订阅服务器并行接收回调?

1 个答案:

答案 0 :(得分:0)

您应该考虑将SendData设置如下。列是平行的,行是顺序的。

订阅者1 |订阅者2 |订阅者3 | ....

发送数据1 |发送数据1 |发送数据1

发送数据2 |发送数据2 |发送数据2

发送数据3 |发送数据3 |发送数据3

.....

我的意思是你可以调用为不同的用户并行发送数据。因此,您一次向多个订阅者发送数据,但同时对于单个订阅者,您应该使其顺序,这样您就不会陷入超时。