#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
withState
beingClosed
… что бы это изменило в вашем коде? в абсолютном лучшем случаеif
вы бы удалилиFaulted
… Я не думаю, что это было бы качеством производства, посколькуFaulted
все еще может произойти по другим причинам…5. @marek что вы могли бы сделать, так это создать «клиентский пул», аналогичный «пулу соединений с БД», а затем каждый раз, когда вы получаете «клиент», «пул» сначала проверяет его и удаляет / воссоздает соответствующим образом… когда вы возвращаете его в «пул», «пул» снова проверяет наличие определенного
State
и удаляет / воссоздает его…