Поделиться через


Использование сеансов

В приложениях Windows Communication Foundation (WCF) используются сеансы, коррелирующие группы сообщений в диалоги. Сеансы в WCF отличны от объектов сеансов в приложениях ASP.NET, они поддерживают другие поведения и по-другому управляются. В этом разделе описаны возможности приложений WCF, обеспечиваемые сеансами, и способы их использования.

Сеансы в приложениях Windows Communication Foundation

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

Сеансы WCF имеют следующие основные особенности:

  • Они явным образом инициируются и завершаются вызвавшим приложением (клиентом WCF).

  • Сообщения, доставленные в ходе сеанса, обрабатываются в порядке их получения.

  • Сеанс коррелирует группу сообщений в диалог. Возможны различные типы корреляций. Например, один основанный на сеансах канал может коррелировать сообщения, основываясь на общем сетевом подключении, а другой — основываясь на общем теге в тексте сообщения. Функции, получаемые в результате сеанса, зависят от характера корреляции.

  • Нет общего хранилища данных, связанного с сеансом WCF.

Зная особенности класса System.Web.SessionState.HttpSessionState в приложениях ASP.NET и обеспечиваемые им функциональные возможности, можно отметить следующие различия между его сеансами и сеансами WCF:

  • Сеансы ASP.NET всегда инициируются сервером.

  • Сеансы ASP.NET явным образом неупорядочены.

  • Сеансы ASP.NET обеспечивают общий механизм хранения данных для запросов.

В этом разделе описываются следующие функции и операции:

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

  • Типы функций, предоставляемых привязками WCF, основанными на сеансе и предоставляемыми системой.

  • Создание контракта, объявляющего требование сеанса.

  • Управление созданием и прекращением сеанса и его связью с экземпляром службы.

Поведение выполнения по умолчанию с использованием сеансов

Привязка, пытающаяся инициировать сеанс, называется основанной на сеансе. Контракты служб указывают о том, что для них требуются, допускаются или не допускаются привязки, основанные на сеансе. Для этого свойству System.ServiceModel.ServiceContractAttribute.SessionMode интерфейса (или класса) контракта службы присваивается одно из значений перечисления System.ServiceModel.SessionMode. По умолчанию это свойство имеет значение Allowed, означающее, что если клиент использует основанную на сеансе привязку с реализацией службы WCF, служба устанавливает и использует предоставленный сеанс.

Когда служба WCF принимает клиентский сеанс, по умолчанию включены следующие функции:

  1. Все вызовы, в которых задействован клиентский объект WCF, обрабатываются одним и тем же экземпляром службы.

  2. Различные привязки на основе сеанса предоставляют дополнительные возможности.

Типы сеансов, предоставляемые системой

Привязка, основанная на сеансе, поддерживает ассоциацию по умолчанию экземпляра службы с определенным сеансом. Впрочем, различные привязки, основанные на сеансе, поддерживают и другие различные функции, помимо описанного выше управления созданием экземпляров на основе сеанса.

WCF обеспечивает следующие типы поведения приложений, основанные на сеансах:

  • Элемент System.ServiceModel.Channels.SecurityBindingElement поддерживает основанные на безопасности сеансы, в которых обе стороны, обменивающиеся информацией, согласовали определенный безопасный диалог. Дополнительные сведения см. в разделе Защита служб. Например, привязка System.ServiceModel.WSHttpBinding, содержащая поддержку как безопасных, так и надежных сеансов, по умолчанию использует только безопасный сеанс, шифрующий сообщения и защищающий их цифровой подписью.

  • Привязка System.ServiceModel.NetTcpBinding поддерживает сеансы, основанные на TCP/IP, что обеспечивает корреляцию всех сообщений по подключению на уровне сокетов.

  • Элемент System.ServiceModel.Channels.ReliableSessionBindingElement, реализующий спецификацию WS-ReliableMessaging, обеспечивает поддержку надежных сеансов, в которых можно настроить отправку сообщений в определенном порядке и только один раз, что гарантирует получение сообщений, даже когда при диалоге они проходят через несколько узлов. Дополнительные сведения см. в разделе Надежные сеансы.

  • Привязка System.ServiceModel.NetMsmqBinding обеспечивает сеансы датаграммы MSMQ. Дополнительные сведения см. в разделе Очереди в Windows Communication Foundation.

Установка свойства SessionMode указывает о том, что для контракта требуется сеанс, но не задает тип этого сеанса.

Создание контракта, требующего сеанс

Создание контракта, требующего сеанс, означает, что группа операций, объявляемых контрактом службы, должна выполняться в пределах одного сеанса и сообщения должны быть доставлены в определенном порядке. Чтобы назначить уровень поддержки сеансов, требуемый контрактом, задайте в качестве значения свойства System.ServiceModel.ServiceContractAttribute.SessionMode класса или интерфейса контракта службы перечисление System.ServiceModel.SessionMode. При этом указывается одно из следующих условий контракта:

  • Требуется сеанс.

  • Клиенту допускается создавать сеанс.

  • Сеансы запрещены.

Впрочем, установка свойства SessionMode не указывает требуемый контрактом тип поведения, основанного на сеансе. Она предписывает WCF подтвердить во время выполнения, что настроенная для службы привязка (создающая коммуникационный канал) устанавливает, не устанавливает или может установить сеанс при реализации службы. Опять же, привязка может выполнить это требование с любым типом поведения, основанного на сеансе: безопасность, транспорт, надежность или некоторая комбинация этих типов. Конкретное поведение зависит от выбранного значения System.ServiceModel.SessionMode. Если настроенная для службы привязка не соответствует значению SessionMode, выдается исключение. Привязки и создаваемые ими каналы, поддерживающие сеансы, называются основанными на сеансах.

Следующий контракт службы указывает, что все операции в ICalculatorSession необходимо выполнить в пределах одного сеанса. Ни одна операция не возвращает значение вызвавшему объекту, за исключением метода Equals. Впрочем, метод Equals не принимает параметры, а потому может возвращать только ненулевое значение в пределах сеанса, в котором данные уже переданы другим операциям. Для правильной работы этого контракта требуется сеанс. При отсутствии сеанса, связанного с определенным клиентом, экземпляр службы не может определить, какие именно данные отправил клиент.

<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession

    <OperationContract(IsOneWay:=True)> _
    Sub Clear()
    <OperationContract(IsOneWay:=True)> _
    Sub AddTo(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub SubtractFrom(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub MultiplyBy(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub DivideBy(ByVal n As Double)
    <OperationContract()> _
    Function Equal() As Double
End Interface
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
    [OperationContract(IsOneWay=true)]
    void Clear();
    [OperationContract(IsOneWay = true)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true)]
    void DivideBy(double n);
    [OperationContract]
    double Equals();
}

Если сеанс разрешен службой, он создается и используется, если он инициирован клиентом. В противном случае сеанс не создается.

Сеансы и экземпляры служб

При использовании поведения создания экземпляров по умолчанию в WCF все вызовы, в которых задействован клиентский объект WCF, обрабатываются одним и тем же экземпляром службы. Таким образом, на уровне приложения можно считать, что сеанс обеспечивает поведение приложений, аналогичное поведению местных вызовов. Например, при создании локального объекта происходит следующее:

  • Вызывается конструктор.

  • Все последующие вызовы по ссылке на клиентский объект WCF обрабатываются одним и тем же экземпляром объекта.

  • Деструктор вызывается при уничтожении ссылки на объект.

Сеансы обеспечивают аналогичное поведение при взаимодействии между клиентами и службами, если используется поведение создания экземпляров службы по умолчанию. Если контракт службы требует или поддерживает сеансы, можно отметить операцию (или несколько операций) как инициирующую или завершающую сеанс. Для этого необходимо задать свойства IsInitiating и IsTerminating.

Инициирующие операции — это операции, вызываемые в качестве первых операций новых сеансов. Неинициирующие операции могут вызываться только после вызова по крайней мере одной инициирующей операции. Поэтому можно создать некоторое подобие конструктора сеансов для службы, объявив инициирующие операции, которые принимают от клиентов входные данные, как подходящие для создания экземпляра службы. (Впрочем, состояние ассоциируется с сеансом, а не с объектом службы.)

Завершающие операции — это, соответственно, операции, вызываемые как последние сообщения существующих сеансов. В случае по умолчанию WCF повторно использует объект службы и его контекст после закрытия сеанса, с которым была связана эта служба. Поэтому можно создать некоторое подобие деструктора, объявив завершающие операции, которые выполняют функции по завершению действия экземпляра службы.

ms733040.note(ru-ru,VS.100).gifПримечание
Поведение по умолчанию имеет сходство с локальными конструкторами и деструкторами, но это не более чем сходство. Любая операция службы WCF может быть инициирующей или завершающей, или и той и другой одновременно. Кроме того, в случае по умолчанию инициирующие операции можно вызывать сколько угодно раз и в любом порядке. После того как сеанс установлен и связан с экземпляром, дополнительные сеансы могут быть созданы только в случае осуществления явным образом управления временем существования экземпляра службы (путем обработки объекта System.ServiceModel.InstanceContext). И наконец, состояние связывается с сеансом, а не с объектом службы.

Например, контракт ICalculatorSession, используемый в приведенном выше примере, требует, чтобы клиентский объект WCF вызывал операцию Clear перед любой другой операцией и чтобы сеанс этого клиентского объекта WCF завершался при вызове операции Equals. В следующем примере кода приведен контракт, обеспечивающий выполнение этих требований. Сначала необходимо вызвать операцию Clear для инициации сеанса, завершаемого в дальнейшем при вызове операции Equals.

<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession

    <OperationContract(IsOneWay:=True, IsInitiating:=True, IsTerminating:=False)> _
    Sub Clear()
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub AddTo(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub SubtractFrom(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub MultiplyBy(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub DivideBy(ByVal n As Double)
    <OperationContract(IsInitiating:=False, IsTerminating:=True)> _
    Function Equal() As Double
End Interface
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
    [OperationContract(IsOneWay=true, IsInitiating=true, IsTerminating=false)]
    void Clear();
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void DivideBy(double n);
    [OperationContract(IsInitiating = false, IsTerminating = true)]
    double Equals();
}

Службы не начинают сеансы с клиентами. В клиентских приложениях WCF существует прямая связь между временем существования канала, основанного на сеансах, и самого сеанса. Таким образом, клиенты создают новые сеансы путем создания новых каналов, основанных на сеансах, и прерывают существующие сеансы путем правильного закрытия этих каналов. Клиент начинает сеанс с конечной точкой службы путем вызова одной из следующих операций:

Обычно клиент завершает сеанс с конечной точкой службы путем вызова одной из следующих операций:

  • System.ServiceModel.ICommunicationObject.Close для канала, возвращенного при вызове System.ServiceModel.ChannelFactory.CreateChannel.

  • System.ServiceModel.ClientBase.Close для клиентского объекта WCF, созданного программой Svcutil.exe.

  • Завершающей операции для клиентского объекта WCF любого типа (по умолчанию все операции не являются завершающими; контракт должен явно указывать завершающую операцию). При вызове первой операции клиентский объект WCF автоматически открывает канал и инициирует сеанс.

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

Дополнительные сведения клиентах и сеансах см. в разделе Обращение к службам с использованием клиента.

Сеансы взаимодействуют с параметрами InstanceContext

Перечисление SessionMode контракта взаимодействует со свойством System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode, управляющим связью между каналами и определенными объектами службы. Дополнительные сведения см. в разделе Сеансы, экземпляры и параллелизм.

Совместное использование объектов InstanceContext

Также можно задать для каждого вызова или канала, основанного на сеансе, с каким именно объектом InstanceContext он будет ассоциирован, самостоятельно назначив ассоциацию. Полный пример содержится в разделе InstanceContextSharing.

Сеансы и потоковая передача

Если требуется передать значительный объем данных, режим потоковой передачи в WCF является выгодной альтернативой поведению по умолчанию, при котором сообщения буферизуются и обрабатываются в памяти целиком. При потоковой передаче вызовов с привязкой, основанной на сеансе, может возникнуть непредвиденное поведение. Все потоковые вызовы выполняются через один канал (канал датаграммы), который не поддерживает сеансы, даже если используемая привязка настроена так, чтобы она использовала сеансы. Если несколько клиентов выполняют потоковые вызовы одного объекта службы через привязку, основанную на сеансе, и задан "одиночный" режим параллелизма объекта службы и задан режим контекста его экземпляра PerSession, все вызовы должны проходить через канал датаграммы, а потому может обрабатываться не более одного вызова одновременно. При этом может истечь время ожидания для одного или нескольких клиентов. Эту проблему можно обойти, присвоив значение PerCall свойству InstanceContextMode или выбрав "множественный" режим параллелизма.

ms733040.note(ru-ru,VS.100).gifПримечание
Свойство MaxConcurrentSessions в данном случае ни на что не влияет, поскольку имеется всего один сеанс.

См. также

Справочник

IsInitiating
IsTerminating