Uso de sesiones
En las aplicaciones de Windows Communication Foundation (WCF), una sesión correlaciona un grupo de mensajes en una conversación. Las sesiones de WCF son diferentes del objeto de sesión disponible en las aplicaciones de ASP.NET, admiten comportamientos diferentes y se controlan de diferente manera. En este tema se describen las características que habilitan las sesiones en las aplicaciones de WCF y cómo utilizarlas.
Sesiones en aplicaciones de Windows Communication Foundation
Cuando un contrato de servicio especifica que requiere una sesión, ese contrato está especificando que todas las llamadas (es decir, los intercambios de mensajes subyacentes que admiten las llamadas) deben formar parte de la misma conversación. Si un contrato especifica que admite sesiones pero no requiere una, los clientes pueden conectarse y establecer o no una sesión. Si la sesión finaliza y se envía un mensaje se envía a través del mismo canal, se produce una excepción.
Las sesiones de WCF tienen las siguientes características conceptuales principales:
La aplicación (el cliente WCF) que realiza la llamada inicia y finaliza explícitamente las sesiones.
Los mensajes entregados durante una sesión se procesan en el orden de recepción.
Las sesiones correlacionan un grupo de mensajes en una conversación. Son posibles distintos tipos de correlaciones. Por ejemplo, un canal basado en sesión puede correlacionar mensajes basados en una conexión de red compartida, mientras que otro canal basado en sesión puede correlacionar mensajes basados en una etiqueta compartida en el cuerpo del mensaje. Las características que se pueden derivar a partir de la sesión dependen de la naturaleza de la correlación.
No hay ningún almacén de datos general asociado a una sesión de WCF.
Si está familiarizado con la clase System.Web.SessionState.HttpSessionState en aplicaciones ASP.NET y la funcionalidad que proporciona, podría observar las siguientes diferencias entre ese tipo de sesión y las sesiones de WCF:
Las sesiones ASP.NET siempre son iniciadas por servidor.
Las sesiones ASP.NET están implícitamente desordenadas.
Las sesiones ASP.NET proporcionan un mecanismo del almacenamiento de datos general para todas las solicitudes.
Este tema describe:
El comportamiento de ejecución predeterminado al utilizar enlaces basados en sesión en el nivel de modelo de servicio.
Los tipos de características que ofrecen los enlaces WCF basados en sesión proporcionados por el sistema.
Cómo crear un contrato que declare un requisito de sesión.
Cómo entender y controlar la creación y finalización de la sesión y la relación de la sesión con la instancia del servicio.
Comportamiento de ejecución predeterminado mediante sesiones
Un enlace que intenta iniciar una sesión se denomina enlace basado en sesión. Los contratos de servicio especifican que requieren, permiten o rechazan enlaces basados en sesión estableciendo la propiedad System.ServiceModel.ServiceContractAttribute.SessionMode en la interfaz (o clase) del contrato de servicio en uno de los valores de enumeración del System.ServiceModel.SessionMode. De forma predeterminada, el valor de esta propiedad es Allowed, que quiere decir que si un cliente utiliza un enlace basado en sesión con una implementación de servicio de WCF, el servicio establece y utiliza la sesión proporcionada.
Cuando un servicio WCF acepta una sesión de cliente, se habilitan las características siguientes de forma predeterminada:
La misma instancia de servicio administra todas las llamadas entre un objeto de cliente de WCF.
Los distintos enlaces basados en sesión proporcionan características adicionales.
Tipos de sesión proporcionados por el sistema
Un enlace basado en sesión admite la asociación predeterminada de una instancia de servicio con una sesión determinada. Sin embargo, diferentes enlaces basados en sesión admiten distintas características además de habilitar el control de creación de instancias basadas en sesión descrito anteriormente.
WCF proporciona los siguientes tipos de comportamiento de aplicaciones basados en sesión:
El System.ServiceModel.Channels.SecurityBindingElement admite sesiones basadas en seguridad, en las que ambos extremos de la comunicación han acordado una conversación segura concreta. Para obtener más información, vea Seguridad de servicios. Por ejemplo, el enlace System.ServiceModel.WSHttpBinding, que admite sesiones de seguridad y sesiones confiables, solo utiliza de forma predeterminada una sesión segura que cifra y firma digitalmente los mensajes.
El enlace System.ServiceModel.NetTcpBinding admite las sesiones basadas en TCP/IP para asegurarse de que todos los mensajes están correlacionados por la conexión en el nivel de socket.
El elemento System.ServiceModel.Channels.ReliableSessionBindingElement, que implementa la especificación de WS-ReliableMessaging, proporciona la compatibilidad para las sesiones confiables en las que los mensajes se pueden configurar para que se entreguen en orden y solo una vez, asegurando que los mensajes se reciban aunque estos viajen por varios nodos durante la conversación. Para obtener más información, vea Sesiones de confianza.
El enlace System.ServiceModel.NetMsmqBinding proporciona sesiones de datagrama de MSMQ. Para obtener más información, vea Colas en Windows Communication Foundation.
Establecer la propiedad SessionMode no especifica el tipo de sesión que el contrato requiere, solo que requiere uno.
Creación de un contrato que requiere una sesión
La creación de un contrato que requiere una sesión hace que el grupo de operaciones que declara el contrato de servicio deba ejecutarse dentro de la misma sesión y que los mensajes deban entregarse en orden. Para validar el nivel de compatibilidad de la sesión que requiere un contrato de servicio, establezca la propiedad System.ServiceModel.ServiceContractAttribute.SessionMode de su clase o interfaz de contrato de servicio en el valor de la enumeración System.ServiceModel.SessionMode para especificar si el contrato:
Requiere una sesión.
Permite a un cliente establecer una sesión.
Prohíbe una sesión.
Establecer la propiedad SessionMode no especifica, sin embargo, el tipo de comportamiento basado en sesión que requiere el contrato. Indica a WCF que confirme en tiempo de ejecución si el enlace configurado (que crea el canal de comunicación) para el servicio establece, no establece o puede establecer una sesión al implementar un servicio. De nuevo, el enlace puede satisfacer ese requisito con cualquier tipo de comportamiento basado en sesión que elija: seguridad, transporte, confiable o alguna combinación. El comportamiento exacto depende del valor de la enumeración System.ServiceModel.SessionMode seleccionada. Si el enlace configurado del servicio no cumple con el valor de SessionMode, se produce una excepción. Los enlaces, y los canales que esos enlaces crean, que admiten sesiones se dice que son basados en sesión.
El siguiente contrato de servicio especifica que todas las operaciones de la ICalculatorSession
se deben intercambiar dentro de una sesión. Ninguna de las operaciones devuelve un valor al llamador, salvo el método Equals
. Sin embargo, el método Equals
no toma ningún parámetro y, por consiguiente, solo puede devolver un valor distinto de cero dentro de una sesión en la que los datos ya se han pasado a otras operaciones. Este contrato requiere que una sesión funcione correctamente. Si no hay una sesión asociada a un cliente concreto, la instancia del servicio no tiene forma de saber qué datos anteriores ha enviado este cliente.
<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();
}
Si un servicio permite una sesión, se establece una sesión y se utiliza si el cliente inicia una; de lo contrario, no se establece ninguna sesión.
Sesiones e instancias de servicios
Si utiliza el comportamiento de creación de instancias predeterminado en WCF, la misma instancia de servicio administra todas las llamadas entre un objeto de cliente de WCF. Por consiguiente, en el nivel de aplicación, puede considerar una sesión como la habilitación de un comportamiento de aplicación similar al comportamiento de la llamada local. Por ejemplo, al crear un objeto local:
Se llama a un constructor.
La misma instancia de objeto procesa todas las llamadas subsiguientes realizadas a la referencia de objeto de cliente de WCF.
Se llama a un destructor cuando se destruye la referencia del objeto.
Las sesiones habilitan un comportamiento similar entre clientes y servicios, siempre que se utilice el comportamiento de instancia de servicio predeterminado. Si un contrato de servicio requiere o admite sesiones, se pueden marcar una o más operaciones del contrato como que inician o finalizan una sesión estableciendo las propiedades IsInitiating y IsTerminating.
Las operaciones de inicio son aquellas que deben llamarse como la primera operación de una nueva sesión. Las operaciones que no son de inicio solo pueden llamarse después de que se haya llamado, al menos, a una operación de inicio. Puede crear, por consiguiente, un tipo de constructor de sesión para su servicio mediante la declaración de operaciones de inicio diseñadas para tomar entradas de clientes apropiadas para el inicio de la instancia de servicio. (Sin embargo, el estado se asocia a la sesión, y no el objeto de servicio).
Las operaciones de finalización, por el contrario, son aquellas a las que se debe llamar como el último mensaje de una sesión existente. En el caso predeterminado, WCF recicla el objeto de servicio y su contexto después de que se cierre la sesión a la que se asoció el servicio. Por consiguiente, puede crear un tipo de destructor declarando operaciones de finalización diseñadas para realizar una función adecuada al final de la instancia de servicio.
Nota: |
---|
Aunque el comportamiento predeterminado se parece algo a los constructores y destructores locales, solo es eso, un parecido. Cualquier operación de servicio de WCF puede ser una operación de inicio o finalización, o ambas al mismo tiempo. Además, en el caso predeterminado, las operaciones de inicio pueden llamarse cualquier número de veces en cualquier orden; no se crean sesiones adicionales una vez que se establezca la sesión y se asocie a una instancia, a menos que controle explícitamente la duración de la instancia del servicio (manipulando el objeto System.ServiceModel.InstanceContext). Finalmente, el estado se asocia a la sesión y no al objeto de servicio. |
Por ejemplo, el contrato de ICalculatorSession
utilizado en el ejemplo anterior requiere que el objeto de cliente de WCF llame primero a la operación Clear
antes que a cualquier otra operación y que la sesión con este objeto de cliente de WCF debería finalizar cuando llame a la operación Equals
. El ejemplo de código siguiente muestra un contrato que exige estos requisitos. Se debe llamar primero a Clear
para iniciar una sesión, y esa sesión finalizará cuando se llame 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();
}
Los servicios no inician sesiones con clientes. En aplicaciones cliente de WCF, existe una relación directa entre la duración del canal basado en sesión y la duración de la propia sesión. Como tal, los clientes crean nuevas sesiones creando nuevos canales basados en sesión y acaban con las sesiones existentes cerrando correctamente los canales basados en sesión. Un cliente inicia una sesión con un extremo de servicio llamando a uno de los siguientes métodos:
System.ServiceModel.ICommunicationObject.Open en el canal devuelto por una llamada a System.ServiceModel.ChannelFactory.CreateChannel.
System.ServiceModel.ClientBase.Open en el objeto de cliente de WCF generado por la Herramienta de utilidad de metadatos de ServiceModel (Svcutil.exe).
Una operación de inicio en cualquier tipo de objeto de cliente de WCF (de forma predeterminada, todas las operaciones son de inicio). Cuando se llama a la primera operación, el objeto de cliente de WCF abre automáticamente el canal e inicia una sesión.
Por lo general, un cliente finaliza una sesión con un extremo de servicio llamando a uno de los siguientes métodos:
System.ServiceModel.ICommunicationObject.Close en el canal devuelto por una llamada a System.ServiceModel.ChannelFactory.CreateChannel.
System.ServiceModel.ClientBase.Close en el objeto de cliente de WCF generado por Svcutil.exe.
Una operación de finalización en cualquier tipo de objeto de cliente de WCF (de forma predeterminada, ninguna operación es de finalización; el contrato debe especificar explícitamente una operación de finalización). Cuando se llama a la primera operación, el objeto de cliente de WCF abre automáticamente el canal e inicia una sesión.
Para obtener ejemplos, vea Cómo crear un servicio que requiere sesiones así como los ejemplos Comportamiento de servicio predeterminado y Creación de instancias.
Para obtener más información sobre clientes y sesiones, vea Acceso a los servicios utilizando un cliente.
Las sesiones interactúan con la configuración de InstanceContext
Hay una interacción entre la enumeración de SessionMode en un contrato y la propiedad System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode, que controla la asociación entre canales y objetos de servicio concretos. Para obtener más información, vea Sesiones, creación de instancias y simultaneidad.
Uso compartido de objetos InstanceContext
También puede controlar qué canal basado en sesión o llamada se asocia a qué objeto InstanceContext realizando esa asociación usted mismo. Para obtener un ejemplo completo, vea InstanceContextSharing.
Sesiones y transmisión por secuencias
Cuando tiene una gran cantidad de datos para transferir, el modo de transferencia de secuencias en WCF es una alternativa factible al comportamiento predeterminado de almacenar en búfer y procesar los mensajes en memoria en su totalidad. Puede obtener un comportamiento inesperado al transmitir mediante secuencias las llamadas con un enlace basado en sesión. Todas las llamadas de transferencias por secuencias se realizan a través de un canal único (el canal del datagrama) que no admite sesiones incluso si el enlace utilizado esté configurado para utilizar sesiones. Si varios clientes realizan llamadas de transferencias por secuencias al mismo objeto de servicio sobre un enlace basado en sesión y el modo de simultaneidad del objeto de servicio se ha establecido como Single y su modo de contexto de instancia está establecido en PerSession, todas las llamadas deben pasar por el canal de datagrama y, por lo tanto, solo se procesa una llamada al mismo tiempo. Uno o más clientes pueden superar el tiempo de espera. Puede solucionar este problema estableciendo InstanceContextMode del objeto de servicio en PerCall o la simultaneidad en múltiple.
Nota: |
---|
MaxConcurrentSessions no influye en este caso porque solo hay una "sesión" disponible. |