WCF как я могу избежать сбоев в каналах, если они закрыты сервером из-за неактивности

#c# #wcf #timeout #wcf-binding

#c# #wcf #тайм-аут #wcf-привязка

Вопрос:

Мой хост службы настроен на закрытие соединения через 10 минут

 <wsHttpBinding>
    <binding receiveTimeout="00:10:00">
</wsHttpBinding>
  

В моем клиентском коде перед использованием сервиса он проверяется. Если он находится в закрытом / сбойном состоянии, он создаст новый.

     public static T ValidateService<T>(ref T service) where T : class
    {
        if (service is IClientChannel)
        {
            IClientChannel channel = service as IClientChannel;
            CommunicationState state = channel.State;
            if (state == CommunicationState.Faulted || state == CommunicationState.Closed)
            {
                // thread safe logic to create new service 
            }
        }
    }
  

Проблема заключается в том, что канал закрыт на стороне сервера и channel.Состояние все равно вернет открытое состояние. После того, как я выполняю удаленный вызов, я получаю ошибочное исключение и из-за receiveTimeout .

Есть ли какой-либо способ установить тайм-аут неактивности на стороне клиента? что-то подобное receiveTimeout="00:10:00" на сервере, но на несколько секунд меньше, поэтому я могу легко закрыть канал от клиента, если он не используется, и моя ValidateService<T> логика создаст новый, если это необходимо.

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

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

Спасибо

Ответ №1:

Вы не можете избежать обработки Faulted и Closed , поскольку всегда возможно, что какая-то сетевая проблема или подобное приведет к ситуации, когда вам придется создать новый Channel

РЕДАКТИРОВАТЬ — согласно комментарию:

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

Комментарии:

1. Итак, нет лучшего способа обработки receiveTimeout на стороне клиента? Я думал о том, чтобы на клиенте был опросник, который либо выполнял бы какое-то сердцебиение, либо красиво закрывал канал, если последний использованный период достаточно длинный. Что-то вроде receiveTimeout, работающего на стороне клиента.

2. @marek В рабочей среде у меня обычно есть клиентская реализация, которая обрабатывает определенные исключения путем воссоздания канала и повторной попытки…

3. я надеялся, что есть встроенный способ закрыть неиспользуемый канал со стороны клиента вместо того, чтобы в конечном итоге создавать поврежденный канал на клиенте. Я понимаю, что сбой в канале может произойти по многим другим причинам, но я удивлен, что нет хорошего способа красиво закрыть неиспользуемый канал от клиента, подобного receiveTimeout.

4. @marek давайте предположим, что есть способ сделать это … тогда результатом будет Channel with State being Closed … что бы это изменило в вашем коде? в абсолютном лучшем случае if вы бы удалили Faulted … Я не думаю, что это было бы качеством производства, поскольку Faulted все еще может произойти по другим причинам…

5. @marek что вы могли бы сделать, так это создать «клиентский пул», аналогичный «пулу соединений с БД», а затем каждый раз, когда вы получаете «клиент», «пул» сначала проверяет его и удаляет / воссоздает соответствующим образом… когда вы возвращаете его в «пул», «пул» снова проверяет наличие определенного State и удаляет / воссоздает его…