WCF ServiceHost падает, когда UserNamePasswordValidator занимает слишком много времени для обработки - PullRequest
1 голос
/ 28 октября 2010

Я обнаружил ситуацию, когда клиент WCF может вызвать сбой WCF ServiceHost, если у ServiceHost есть UserNamePasswordValidator, для обработки которого требуется некоторое время. Я хотел бы услышать любые предложения о решениях, прежде чем отправлять это в Microsoft.

Шаги для воспроизведения:

  1. Открыть канал
  2. Вызовите метод API, для возврата которого требуется 10 секунд.
  3. Закройте канал перед возвратом метода API.
  4. Метод API возвращается. Сбой ServiceHost.

Вышеуказанное происходит только в том случае, если UserNamePasswordValidator требуется некоторое время для обработки (в моем примере это 2 секунды сна). Если UserNamePasswordValidator немедленно возвращается, ситуация, описанная выше, меняется:

  1. Открыть канал
  2. Вызовите метод API, для возврата которого требуется 10 секунд.
  3. Закройте канал перед возвратом метода API.
  4. Закрытие канала ожидает ожидающего вызова метода API.
  5. Метод API возвращает.
  6. Канал закрывается. Все хорошо.

Код клиента выглядит следующим образом:

public static void Main(string[] args)
{
    var binding = new NetTcpBinding(SecurityMode.TransportWithMessageCredential);
    binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
    var identity = new DnsEndpointIdentity("Dummy");
    var endpointAddress = new EndpointAddress(new Uri("net.tcp://localhost:5000/"), identity);
    var channelFactory = new ChannelFactory<IService>(binding, endpointAddress);

    channelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
    channelFactory.Credentials.UserName.UserName = "foo";
    channelFactory.Credentials.UserName.Password = "bar";

    channelFactory.Open();

    IService service = channelFactory.CreateChannel();

    ThreadPool.QueueUserWorkItem(CallPingOnChannel, service);

    Thread.Sleep(TimeSpan.FromSeconds(1));

    channelFactory.Close();
}

private static void CallPingOnChannel(object state)
{
    var result = ((state) as IService).Ping();
}

ServiceHost настроен следующим образом:

public static void Main(string[] args)
{
    var serviceHost = new ServiceHost(typeof(Service), TcpBaseAddress);
    serviceHost.Description.Behaviors.Add(new ErrorHandler());
    var netTcpBinding = new NetTcpBinding(SecurityMode.TransportWithMessageCredential);
    netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
    netTcpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

    serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
    serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new UserValidator();

    serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
    serviceHost.Credentials.ServiceCertificate.Certificate = GetCertificate();

    serviceHost.AddServiceEndpoint(typeof(IService), netTcpBinding, "");

    serviceHost.Open();

    Console.ReadLine();
}

И UserValidator реализован следующим образом:

public class UserValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        Thread.Sleep(TimeSpan.FromSeconds(2));
    }
}

Необработанное исключение, вызывающее сбой основного потока:

System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '10675199.02:48:05.4775807'. ---> System.IO.IOException: The read operation failed, see inner exception. ---> System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '10675199.02:48:05.4775807'. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

Ответы [ 2 ]

3 голосов
/ 13 декабря 2010

Отвечая на мой собственный вопрос;Я сообщил об этом в Microsoft, и они подтвердили, что это ошибка в платформе, которая будет исправлена ​​в следующей версии.

Ссылка: http://connect.microsoft.com/wcf/feedback/details/622164/wcf-servicehost-crashes-when-usernamepasswordvalidator-takes-too-long-to-process

0 голосов
/ 28 октября 2010

Во-первых, вы должны перехватить исключение System.TimeOutException в коде своего клиента.

Далее вы должны рассмотреть возможность расширения SendTimeout и RecieveTimeout вашего Клиента и Службы.

Взгляните на эти две ссылки.

Свойство SendTimeOut

Свойство RecieveTimeOut

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...