Поделиться через


Примеры устранения неполадок WCF

В этом разделе приведено несколько известных проблем, с которыми столкнулись пользователи при разработке клиентов и служб WCF. Если проблема, с которой столкнулись вы, отсутствует в этом списке, рекомендуется настроить трассировку для данной службы. При этом будет создан файл трассировки, который можно просмотреть с помощью средства просмотра файлов трассировки и получить подробные сведения об исключениях, которые могут возникать в службе. Дополнительные сведения о настройке трассировки см. в разделе Настройка трассировки. Дополнительные сведения о средстве просмотра файлов трассировки см. в разделе Программа Service Trace Viewer (SvcTraceViewer.exe).

  1. Иногда при втором запросе возникает исключение MessageSecurityException, если клиент бездействует некоторое время после первого запроса. В чем причина?

  2. Когда со службой взаимодействует около 10 клиентов, она отклоняет подключение новых клиентов. В чем причина?

  3. Можно ли загружать конфигурацию службы из расположения, отличного от файла конфигурации приложения WCF?

  4. Служба и клиент работают нормально, но их не удается запустить, если клиент находится на другом компьютере. В чем причина?

  5. При создании FaultException<Exception>, где типом является исключение, клиент всегда получает исключение FaultException общего, а не универсального типа. В чем причина?

  6. Создается впечатление, что односторонние операции, а также операции запроса-ответа возвращаются примерно с той же скоростью, что и ответы без данных. В чем причина?

  7. В службе используется сертификат X.509, при этом получается исключение System.Security.Cryptography.CryptographicException. В чем причина?

  8. В имени первого параметра операции прописные буквы были заменены на строчные, и теперь клиент выдает исключение. В чем причина?

  9. При использовании одного из средств трассировки получено исключение EndpointNotFoundException. В чем причина?

What is the base address? How does it relate to an endpoint address?

Иногда при втором запросе возникает исключение MessageSecurityException, если клиент бездействует некоторое время после первого запроса. В чем причина?

Сбой второго запроса может произойти по двум причинам: (1) истекло время ожидания сеанса или (2) перезапущен веб-сервер, на котором размещена служба. В первом случае сеанс действителен до того, как истечет время ожидания службы. Если служба не получает запрос от клиента в течение времени, заданного в привязке службы (ReceiveTimeout), служба завершает сеанс безопасности. Последующие сообщения клиента приводят к исключению MessageSecurityException. Клиент должен повторно установить безопасный сеанс со службой, чтобы отправлять будущие сообщения, или использовать маркер контекста безопасности с отслеживанием состояния. Маркеры контекста безопасности с отслеживанием состояния позволяют не прерывать безопасный сеанс во время перезапуска веб-сервера. Дополнительные сведения использовании маркеров контекста безопасности с отслеживанием состояния см. в разделе Как создать маркер контекста безопасности с отслеживанием состояния для безопасного сеанса. Кроме того, можно отключить безопасные сеансы. При использовании привязки <wsHttpBinding> свойству establishSecurityContext можно задать значение false, чтобы отключить безопасные сеансы. Чтобы отключить безопасные сеансы для других привязок, необходимо создать пользовательскую привязку. Подробные сведения о создании пользовательской привязки см. в разделе Как создавать пользовательскую привязку с использованием элемента SecurityBindingElement. Перед применением этих параметров необходимо разобраться с требованиями безопасности приложения.

Когда со службой взаимодействует около 10 клиентов, она отклоняет подключение новых клиентов. В чем причина?

По умолчанию службы поддерживают не более 10 параллельных сеансов. Поэтому при использовании в привязках службы сеансов, служба принимает подключения новых клиентов до достижения этого числа. После этого служба отклоняет подключения новых клиентов, пока не будет закрыт один из текущих сеансов. Поддержку большего количества клиентов можно обеспечить несколькими способами. Если для службы не требуются сеансы, не используйте сеансовую привязку. (Дополнительные сведения см. в разделе Использование сеансов.) Можно также увеличить ограничение сеансов, установив подходящее значение для свойства MaxConcurrentSessions.

Можно ли загружать конфигурацию службы из расположения, отличного от файла конфигурации приложения WCF?

Да, но необходимо создать пользовательский класс ServiceHost, переопределяющий метод ApplyConfiguration. Внутри этого метода можно вызвать базовый класс, чтобы сначала загрузить конфигурацию (если дополнительно требуется загрузить сведения о стандартной конфигурации), но можно также полностью заменить систему загрузки конфигурации. Обратите внимание, что если требуется загрузить конфигурацию из файла, отличного от файла конфигурации приложения, необходимо самостоятельно выполнять анализ файла и загрузить конфигурацию.

В следующем примере кода показано, как переопределить метод ApplyConfiguration и напрямую настроить конечную точку.

public class MyServiceHost : ServiceHost
{
  public MyServiceHost(Type serviceType, params Uri[] baseAddresses)  
    : base(serviceType, baseAddresses)
  { Console.WriteLine("MyServiceHost Constructor"); }

  protected override void ApplyConfiguration()
  {
    string straddress = GetAddress();
    Uri address = new Uri(straddress);
    Binding binding = GetBinding();
    base.AddServiceEndpoint(typeof(IData), binding, address);
  }

  string GetAddress()
  { return "http://MyMachine:7777/MyEndpointAddress/"; }

  Binding GetBinding()
  {
    WSHttpBinding binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.None;
    return binding;
  }
}

Служба и клиент работают нормально, но их не удается запустить, если клиент находится на другом компьютере. В чем причина?

В зависимости от исключения возможны следующие причины.

  • Возможно, потребуется использовать для адреса конечной точки клиента имя узла, а не "localhost".

  • Возможно, для приложения потребуется открыть порт. Дополнительные сведения см. в разделе Инструкции брандмауэра образцов пакета SDK.

  • Другие возможные причины этой проблемы см. в разделе образцов Running the Samples in a Workgroup and Across Machines.

  • Если в клиенте используются учетные данные Windows и создается исключение SecurityNegotiationException, настройте Kerberos, как указано ниже.

    1. Добавьте учетные данные идентификации в элемент конечной точки в файле конфигурации клиента App.config.

      <endpoint 
        address="http://MyServer:8000/MyService/" 
        binding="wsHttpBinding" 
        bindingConfiguration="WSHttpBinding_IServiceExample" 
        contract="IServiceExample" 
        behaviorConfiguration="ClientCredBehavior" 
        name="WSHttpBinding_IServiceExample">
        <identity>
          <userPrincipalName value="name@corp.contoso.com"/>
        </identity>
      </endpoint>
      
    2. Для этого запустите службу от имени учетной записи System или NetworkService. Чтобы создать командное окно в учетной записи System, выполните следующую команду.

      at 12:36  /interactive "cmd.exe"
      
    3. Разместите службу в службах IIS, которые по умолчанию используют учетную запись имени участника службы (SPN).

    4. Зарегистрируйте в домене новое имя участника службы (SPN) с помощью программы SetSPN. Обратите внимание, что для этого потребуются права администратора домена.

Дополнительные сведения протоколе Kerberos см. в разделе Основные понятия безопасности, используемые в WCF и:

При создании FaultException<Exception>, где типом является исключение, клиент всегда получает исключение FaultException общего, а не универсального типа. В чем причина?

Настоятельно рекомендуется создать свой собственный пользовательский тип данных об ошибке и объявить его в качестве типа сведений в контракте сбоя. Это необходимо, так как при использовании типов исключений, предоставляемых системой, могут возникнуть следующие проблемы.

  • Создается зависимость типов, которая не дает возможности воспользоваться одним из главных преимуществ приложений, ориентированных на службы.

  • Не удается воспользоваться стандартной сериализацией исключений. Некоторые из них, например SecurityException, могут вообще не сериализоваться.

  • Внутренние сведения сериализации доступны для клиентов. Дополнительные сведения см. в разделе Задание и обработка сбоев в контрактах и службах.

Однако при отладке приложения можно сериализовать сведения об исключении и возвратить их клиенту с помощью класса ServiceDebugBehavior.

Создается впечатление, что односторонние операции, а также операции запроса-ответа возвращаются примерно с той же скоростью, что и ответы без данных. В чем причина?

Если указывается, что операция является односторонней, это лишь означает, что контракт операции принимает входящее сообщение и не возвращает выходное сообщение. В WCF все вызовы клиентов возвращаются, когда исходящие данные переданы по каналам связи или возникло исключение. Односторонние операции выполняются таким же образом, и они могут создавать исключение, если не удается обнаружить службу, или заблокировать выполнение, если служба не готова к приему данных из сети. В WCF односторонние вызовы обычно возвращаются к клиенту быстрее, чем операции запроса-ответа. Однако любое условие, замедляющее отправку исходящих данных по сети, одинаково замедляет как односторонние операции, так и операции запроса-ответа. Дополнительные сведения см. в разделе см. в разделах One-Way Services и Обращение к службам с использованием клиента.

В службе используется сертификат X.509, при этом получается исключение System.Security.Cryptography.CryptographicException. В чем причина?

Обычно это происходит после изменения учетной записи пользователя, в которой выполняется рабочий процесс IIS. Например, эта ошибка может возникнуть в Windows XP при изменении учетной записи по умолчанию, в которой выполняется процесс Aspnet_wp.exe, с ASPNET на пользовательскую учетную запись. Если используется закрытый ключ, его процесс должен иметь разрешение для доступа к файлу с этим ключом.

В этом случае необходимо предоставить учетной записи процесса права доступа для чтения файла с закрытым ключом. Например, если рабочий процесс IIS выполняется в учетной записи Бориса, ему необходимо предоставить права доступа для чтения файла, содержащего закрытый ключ.

Дополнительные сведения , как предоставить нужной учетной записи пользователя доступ к файлу с закрытым ключом для конкретного сертификата X.509, см. разделе Как предоставить доступ к сертификатам X.509 для WCF.

В имени первого параметра операции прописные буквы были заменены на строчные, и теперь в клиенте выдается исключение. В чем причина?

Значения имен параметров в сигнатуры операции являются частью контракта и чувствительны к регистру. Используйте атрибут System.ServiceModel.MessageParameterAttribute, чтобы различать имя локального параметра и метаданные, описывающие операцию для клиентских приложений.

При использовании одного из средств трассировки получено исключение EndpointNotFoundException. В чем причина?

Если используется средство трассировки, отличное от механизма трассировки по умолчанию в WCF и получено исключение EndpointNotFoundException, указывающее на несоответствие фильтра адресов, необходимо задействовать класс ClientViaBehavior, чтобы направить сообщения в средство трассировки для их дальнейшего перенаправления на адрес службы. Класс ClientViaBehavior изменяет заголовок адресации Via , чтобы задать следующий сетевой адрес отдельно от конечного получателя, указанного заголовком адресации To. Однако при этом не следует изменять адрес конечной точки, используемый для установки значения To.

В следующем примере кода показан пример файла конфигурации клиента.

<endpoint 
  address=https://localhost:8000/MyServer/
  binding="wsHttpBinding"
  bindingConfiguration="WSHttpBinding_IMyContract"
  behaviorConfiguration="MyClient" 
  contract="IMyContract" 
  name="WSHttpBinding_IMyContract">
</endpoint>
<behaviors>
  <endpointBehaviors>
    <behavior name="MyClient">
      <clientVia viaUri="https://localhost:8001/MyServer/"/>
    </behavior>
  </endpointBehaviors>
</behaviors>

Что такое базовый адрес? Как он связан с адресом конечной точки?

Базовый адрес — это корневой адрес для класса ServiceHost. По умолчанию, если в конфигурацию службы добавлен класс ServiceMetadataBehavior, язык описания веб-служб (WSDL) для всех конечных точек, публикуемых узлом, извлекается из базового HTTP-адреса, относительного адреса, предоставленного поведением метаданных, а также "?wsdl". Если вы знакомы с ASP.NET и IIS, базовый адрес эквивалентен виртуальному каталогу.

Совместное использование порта конечными точками службы и обмена метаданными при помощи NetTcpBinding

Если указать в качестве адреса базы службы net.tcp://MyServer:8080/MyService и добавить следующие конечные точки:

<services>
      <service name="Microsoft.Samples.NetTcp.CalculatorService">
        <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>

А если модифицировать один из параметров NetTcpBinding, как показано в следующем фрагменте конфигурации:

<bindings>
      <netTcpBinding>
        <binding closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="11" maxReceivedMessageSize="65536">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
          <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
          <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
          </security>
        </binding>
      </netTcpBinding>
    </bindings>

Появится следующее сообщение об ошибке: Необработанное исключение: System.ServiceModel. AddressAlreadyInUseException. Уже есть прослушиватель на конечной точке IP 0.0.0.0:9000. Можно обойти эту ошибку, указав полный URL-адрес с другим портом для конечной точки MEX, как показано в следующем фрагменте конфигурации:

<services>
      <service name="Microsoft.Samples.NetTcp.CalculatorService">
        <endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>
        <endpoint address="net.tcp://localhost:9001/servicemodelsamples/mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>

См. также

Основные понятия

Отладка ошибок проверки подлинности Windows