TCP-клиенты WCF - основные рекомендации по их использованию? - PullRequest
9 голосов
/ 02 июня 2011

У меня есть служба WCF, и я хочу подключиться к ней с помощью привязки TCP. Это все хорошо, но как вы должны обращаться с клиентами? Я заметил, что если вы создаете нового клиента для каждого вызова, он не использует канал повторно и оставляет вокруг множество TCP-соединений до истечения времени ожидания.

Это нормальное использование для создания клиента, вызова метода, а затем его закрытия?

Что если вы хотите повторно использовать соединение? Каковы ограничения на это? Можно ли совершать одновременные звонки из разных тем? Если вы не можете, вы должны сделать свой собственный пул соединений? А при повторном использовании соединения необходимо проверить состояние соединения перед выполнением вызовов и очистить его, если оно неисправно?

Ответы [ 2 ]

17 голосов
/ 02 июня 2011

Ну, это много вопросов вместе, и ситуация действительно немного сложна.Когда вы создаете клиента, вы можете сделать это либо через ссылку на службу и получить класс, полученный из ClientBase<ServiceContract>, либо вы можете использовать ChannelFactory<ServiceContract> и создавать каналы вручную (в первом случае внутренне используется ChannelFactory).

Как это относится к вашему вопросу?Давайте сначала посмотрим на настоящее соединение TCP.Когда вы определяете NetTcpBinding, вы можете установить его MaxConnections свойство (по умолчанию 10).Это свойство определяет номер пула соединения.Это означает, что если вы создаете клиентский канал на сервере и закрываете канал, соединение не прерывается немедленно.Он остается открытым в пуле, пока он не будет использован другим открытым клиентским каналом для того же сервера или пока не истечет время его простоя.Вы можете открыть столько соединений, сколько позволяет сервер, но после закрытия соответствующих клиентских каналов будет объединено только число, определенное MaxConnections.Другие соединения будут разорваны немедленно.Если вы создаете CustomBinding, вы можете использовать транспорт TCP напрямую, где вы также можете контролировать время простоя (я думаю, по умолчанию 2 минуты).Соединения объединяются до тех пор, пока соответствующий ChannelFactory не будет уничтожен = используйте один ChannelFactory для приложения (ClientBase сделайте это внутренне).

Теперь давайте поговорим о самом канале, потому что он связан с вашим другимвопросы.WCF отличается сессионными и бессессионными каналами.TcpTransportChannel является сессионным.Это означает, что, открыв канал, вы создаете сеанс.Сеанс означает, что все запросы от одного клиентского прокси-сервера по умолчанию всегда обслуживаются одним и тем же экземпляром службы (для каждого экземпляра сеанса).Но экземпляр по умолчанию однопоточный.Это означает, что вы можете иметь несколько потоков, используя один и тот же прокси, но служба будет обрабатывать запросы в последовательном порядке.Если вы хотите, чтобы ваш сервис обрабатывал несколько запросов одновременно, вы должны пометить его [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple].Как только вы это сделаете, вы несете ответственность за многопоточную обработку в службе (несколько потоков обращаются к одному экземпляру службы).

Сессионные каналы имеют один большой недостаток.Любой сбой или исключение в службе нарушит работу канала, и вы, как правило, узнаете об этом после повторной попытки использования канала (исключение говорит о том, что канал находится в состоянии сбоя и не может использоваться).Вы должны всегда правильно обрабатывать эти ситуации, и вы должны правильно закрывать каналы / прокси, если вы не хотите их использовать, или прервать их, если они неисправны.Неисправный канал не может быть восстановлен - он должен быть прерван, и вы должны создать новый прокси / канал.Я не уверен, возвращаются ли соединения в пул, если вы этого не сделаете.

Повторное использование прокси / канала зависит от типа приложения, которое вы создаете.Я определенно не буду повторно использовать прокси / канал для нескольких запросов в веб-приложении, но повторное использование абсолютно нормально в WinForm или WPF-приложении.

Редактировать:

Да ClientBase использует ChannelFactory внутренне.Способ использования ChannelFactory со временем изменился.В .NET 3.0 фабрика была создана для каждого экземпляра ClientBase.Начиная с .NET 3.5 WCF использует внутренний кэш MRU (используется в последнее время), который кэширует до 32 последних использованных фабрик.Чтобы воспользоваться этим кэшированием, вы должны использовать прокси-конструктор без параметров или с endpointConfigurationName и remoteAddress / EndpointAddress.Вы не должны создавать конечную точку в коде - эти прокси не используют кеш.Подробнее о теме здесь .

0 голосов
/ 02 июня 2011

Вы закрываете свои сервисные прокси на стороне клиента?

IService service = channelFactory.CreateChannel();

service.DoStuff();

((IContextChannel) service).Close();

Это относится ко всем клиентам WCF, независимо от того, является ли привязка TCP или нет.

Для получения дополнительной информации см .: http://msdn.microsoft.com/en-us/library/aa355056.aspx

...