Подтвердить что ты не робот

Почему WCF не поддерживает тайм-ауты на стороне службы?

Недавно мы обнаружили, что WCF не поддерживает операции тайм-аута со стороны обслуживания (обратите внимание, сторона обслуживания, а не клиентская сторона). В то время как клиент отключается по истечении указанного времени, наше тестирование показало, что для netNamedPipeBinding, netTcpBinding и basicHttpBinding никакой тайм-аут, который мы укажем, приведет к остановке операции обслуживания после ее вызова. Ниже приведены конкретные конфигурации привязки, которые мы пробовали:

<bindings>
  <netNamedPipeBinding>
    <binding name="TestServiceBindingConfigurationNamedPipe"
             receiveTimeout="00:00:05"
             sendTimeout="00:00:05"
             closeTimeout="00:00:05"
             openTimeout="00:00:05" />
  </netNamedPipeBinding>
  <netTcpBinding>
    <binding name="TestServiceBindingConfigurationTcp"
             receiveTimeout="00:00:05"
             sendTimeout="00:00:05"
             closeTimeout="00:00:05"
             openTimeout="00:00:05" />
  </netTcpBinding>
  <basicHttpBinding>
    <binding name="TestServiceBindingConfigurationBasicHttp"
             receiveTimeout="00:00:05"
             sendTimeout="00:00:05"
             closeTimeout="00:00:05"
             openTimeout="00:00:05" />
  </basicHttpBinding>
</bindings>

Наша реализация тестовой службы выглядит следующим образом:

public class TestServiceImpl : ITestService
{
    public TestResult TestIt(TestArgs args)
    {
        var stopwatch = new Stopwatch();
        stopwatch.Start();

        // this is a contrived example, but it shows that WCF never stops this thread
        while (true)
        {
            Console.WriteLine("{0}> I'm running forever...", stopwatch.Elapsed);
        }

        return new TestResult {Result = "Args were " + args.Args};
    }
}

Используя netNamedPipeBinding и netTcpBinding, наше клиентское приложение истечет через 5 секунд, но служба будет продолжаться неограниченное время.

Это приводит к моему вопросу (-ам) - - это ошибка? Существует ли конкретная причина, по которой WCF не хочет отключать службы, если они работают дольше, чем ожидалось?

С моей точки зрения, некоторые из возможных негативных проблем с этим включают:

  • Ограничение по умолчанию для экземпляров службы равно 10. Поэтому, если у вас есть плохой код в вашей службе, который работает вечно, и он попадает в 10 раз, ваш сервис полностью отключится; новые соединения не принимаются.
  • Не существует никакой видимости того факта, что службы выполняются навсегда - кроме пользовательских протоколов или, возможно, с помощью счетчиков производительности
  • Любые ресурсы, которые используются вызовом службы, могут храниться неограниченно (например, SQL-строка, страница и блокировки таблиц), если нет других механизмов для тайм-аута операции.
4b9b3361

Ответ 1

Если у вас есть плохой код, который работает навсегда, выбор времени может только ухудшить ситуацию. Исправить плохой код, если это вообще возможно! См. статью Эрика Липперта, Осторожно с этим тоном, о подобных ситуациях.

Если это находится в разработке, вы можете попробовать настроить System.Threading.Timer, который вызывает serviceCallThread.Abort() в вашей реализации службы. Однако убедитесь, что вы полностью отключили таймер перед возвратом - этот подход безумно подвержен ошибкам из-за сочетания проблем concurrency, не владеющих потоком, по которому вызов службы прибывает, странное поведение ThreadAbortException, а также вопросы, которые Эрик объясняет о слепом завершающем коде, который ушел в сорняках.

Ответ 2

Я сам заметил эту проблему... Я не могу придумать, почему они не будут включать тайм-ауты на стороне службы как часть платформы.

Ответ 3

Как насчет:

<system.web>
    <httpRuntime executionTimeout="inSeconds"/>
</system.web>