Инициализация времени выполнения прокси WCF и влияние на производительность

Я инициализирую свой прокси вручную через класс ChannelFactory, поскольку конфигурации для инициализации этого прокси взяты из какой-то другой службы конфигурации (не в том же App.Config) и, чтобы избежать затрат на инициализацию (вызов службы, чтение параметров конфигурации), я кэшировал этот прокси. Я не могу нести затраты на закрытие этого прокси после каждой операции, потому что требуется частое выполнение операций. Конфигурации тайм-аута для этого прокси следующие.

receiveTimeout="00:10:00" 
sendTimeout="00:10:00" 
closeTimeout="00:10:00"

Согласно моему пониманию свойств тайм-аута на стороне клиента, статус моего прокси-сервера будет Fault, когда тайм-аут превысит. правильно?

Я хочу повторно инициализировать свой прокси, поэтому у меня есть 2 варианта сделать это.

1) Я использую обработчик событий ICommunicationObject.Faaled, и когда мой прокси перешел в состояние сбоя, я даже повторно инициализирую прокси. Но эта реализация не подходит, потому что мы неправильно разместили прокси (вызов метода .Close ()), и он не освободит ресурсы со стороны службы и не повлияет на мою производительность.

2) Я создаю поток и устанавливаю, что прошло несколько секунд, прежде чем прокси перейдет в состояние сбоя. Правильно закройте этот прокси, вызвав метод .Close {), повторно инициализируйте другой объект и кешируйте его.

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

Заранее спасибо.


person Rizwan    schedule 27.09.2011    source источник


Ответы (1)


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

Я обычно иду и пишу небольшой прокси, который просто публикует события Connected и Fault. И я реализую IDisposable с помощью кода, который сначала пытается закрыть прокси, а когда возникает исключение CommunicationException, он прерывает его.

В коде, который обрабатывает обмен данными, я держу ссылку на такой прокси-объект и удаляю его в Close / Fault и открываю его, как только у меня есть ожидающая операция. Это довольно хорошо работает на стороне клиента, даже когда сеть ненадежна. В случае Duplex-Services я просто добавляю таймер, который пытается автоматически переподключиться, если соединение потеряно.

Вот небольшой фрагмент на F #, демонстрирующий, как я использую этот очень простой прокси - на самом деле это не более чем упаковка канала и получение выходных событий соединения - WcfHelper - это просто набор вспомогательных функций для создания адресов и привязок - в этом случае - это урезанная версия для DuplexService, поэтому она наследуется от DuplexClientBase, но нормальный недуплексный случай остается таким же.

/// Duplex-proxy
type private MyProxy(handler, servicename: string, server : string, port : int) =
    inherit DuplexClientBase<IWcfConnector>(handler, WcfHelper.getBinding(), WcfHelper.createEndpointAddress(servicename, server, port))

    let _connectionEvent = new Event<_>()

    do
        base.InnerDuplexChannel.Closed.Add(fun _ -> _connectionEvent.Trigger(ConnectionState.Disconnected))
        base.InnerDuplexChannel.Opened.Add(fun _ -> _connectionEvent.Trigger(ConnectionState.Connected))
        base.InnerDuplexChannel.Faulted.Add(fun _ -> _connectionEvent.Trigger(ConnectionState.Disconnected))

    /// sample-Operation
    member i.TestCall(message) = base.Channel.TestCall(message)

    interface IDisposable with
        member i.Dispose() =
            try
                i.Close()
            with
            | :? CommunicationException ->
                i.Abort()
person Random Dev    schedule 28.09.2011
comment
Вызов Abort () освобождает ресурсы только со стороны клиента. При вызове Close () освобождайте ресурсы и со стороны сервиса. Например, если я установил MaxConcurrentInstances = 1 и InstanceContextMode = PerCall, это означает, что один экземпляр прокси-сервера может обслуживать / подключаться к службе за раз. что, если я удерживаю этот экземпляр прокси, и он переходит в состояние сбоя, а затем я вызываю Abort () и пытаюсь повторно инициализировать его, любая служба разрешит / поддержит этот экземпляр прокси, потому что другой экземпляр не был корректно закрыт на стороне службы? - person Rizwan; 28.09.2011
comment
Если прокси находится в неисправном состоянии, вы ничего не можете с этим поделать. Что делать, если ваше сетевое соединение потеряно? Нет IMHO MaxConcurrentInstances (в сценарии PerCall) только сообщает серверу, сколько Service-Object он может создать за один раз - если это один и приходит другой вызов, вызову просто нужно будет дождаться завершения первого экземпляра. - person Random Dev; 28.09.2011
comment
Вы правы, MaxConcurrentInstances только сообщает серверу, сколько Service-Object он может создать. Пожалуйста, поправьте меня, если я ошибаюсь, прокси-сервер начинает связь со службой, но не вызывает / не вызывает метод Close (), я предполагаю, что служба не будет удалять InstanceContext (и связанные ресурсы) одновременно, если ему пришел другой вызов будет оставаться в состоянии ожидания, пока прокси1 не вызовет метод Close (). - person Rizwan; 28.09.2011
comment
Это может зависеть от типа прокси / вызова / INstanceContextMode, и мне нужно было бы прочитать документы или проверить его, чтобы быть уверенным, но я думаю, что сервер вообще не задействован в закрытии клиента. В этой ситуации (для каждого вызова) это почти то же самое, что и с ASP.NET - объект-служба создается по вызову, вызывается член и все. - person Random Dev; 28.09.2011
comment
ОК, Карстен. Я тоже попробовал протестировать этот сценарий и поделюсь с вами. Не могли бы вы поделиться кодом прокси, который вы написали для публикации событий Connected и Fault, и реализовать IDisposable с кодом, который сначала пытается закрыть прокси, а когда генерируется исключение CommunicationException, переходит к Abort, которое вы упомянули в своем ответе, или обратитесь к любой статье или базе знаний. Это должно быть полезно для меня. - person Rizwan; 28.09.2011
comment
Чтобы понять код F #, мне понадобится конвертер F #. Было бы здорово, если бы вы преобразовали его на C #. - person Rizwan; 28.09.2011
comment
извините, чувак, но, честно говоря, для нулевого выигрыша здесь требуется много работы - код не делает ничего больше, чем я сказал в тексте над ним - он ОЧЕНЬ прямолинейный и только обертывает 3 события в одно с в основном перечислением - Результат говорит, что подключен / отключен. - person Random Dev; 28.09.2011