Instancecontextmode is the instance mode for the server to implement the service contract class. There are three types: percall-each service operation call is created once,
After the call is complete, destroy it. persession-this is created once during the same session, and the first operation (isinitiating = true) of the client proxy is created,
Call the close method of the proxy to destroy or call the isterminating service to destroy the service. The single-service is created only once.
Destruction Upon completion
Sessionmode is the session mode between the client proxy and the server. There are also three types: allowed-allow sessions, notallowed-do not allow sessions, required-require sessions (requires binding support for sessions, wshttpbinding, nettcpbinding, etc)
This article is a test and Comparison of Different session modes in different instance modes. The code is from the attach article.
The test code and configuration file describe the service contract:
[ServiceContract] public interface ICalculator { [OperationContract(IsOneWay = true)] void Add(double x); [OperationContract] double GetResult(); }
Service Contract implementation:
[ServiceBehavior] class CalculatorService :appledou.Test.WCF.Contract.ICalculator, IDisposable { private double _result; #region ICalculator Members public void Add(double x) { Console.WriteLine("The Add method is invoked and the current SessionID is: {0}", OperationContext.Current.SessionId); this._result += x; } public double GetResult() { Console.WriteLine("The GetResult method is invoked and the current SessionID is: {0}\r\n", OperationContext.Current.SessionId); return this._result; } #endregion public CalculatorService() { Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("Calculator object has been created"); Console.ResetColor(); }
#region IDisposable Members public void Dispose() { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("The IDisposable.Dispose method is invoked\r\n"); Console.ResetColor(); } #endregion }
The parameters of the add method are accumulated in the Variable _ result class, and finally returned through getresult. At the same time, the current sessionid is output in each method.
Functions and dispose Methods output call information to facilitate observation of server behavior.
Server configuration file:
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="CalculatorBehavior"> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <wsHttpBinding> <binding name="wsHttp"> <reliableSession enabled="true" inactivityTimeout="00:00:30"/> </binding> </wsHttpBinding> </bindings> <services> <service name="appledou.Test.WCF.Service.CalculatorService" behaviorConfiguration="CalculatorBehavior">
Binding is the wshttpbinding that supports sessions.
Client call code:
ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("Calculator");Console.WriteLine("Create a calculator proxy: proxy1");ICalculator proxy1 = channelFactory.CreateChannel();Console.WriteLine("Invocate proxy1.Add(1)");proxy1.Add(1);Console.WriteLine("Invocate proxy1.Add(2)");proxy1.Add(2);Console.WriteLine("The result return via proxy1.GetResult() is : {0}\r\n", proxy1.GetResult());(proxy1 as ICommunicationObject).Close();
//---------------------------------Console.WriteLine("Create a calculator proxy: proxy2");ICalculator proxy2 = channelFactory.CreateChannel();Console.WriteLine("Invocate proxy2.Add(1)");proxy2.Add(1);Console.WriteLine("Invocate proxy2.Add(2)");proxy2.Add(2);Console.WriteLine("The result return via proxy2.GetResult() is : {0}", proxy2.GetResult());(proxy2 as ICommunicationObject).Close();
Client configuration file:
<system.serviceModel> <client> <endpoint name="Calculator" address="http://localhost:8888/Calculator" binding="wsHttpBinding" bindingConfiguration="wsHttp" contract="appledou.Test.WCF.Contract.ICalculator"/> </client> <bindings> <wsHttpBinding> <binding name="wsHttp"> <reliableSession enabled="true" inactivityTimeout="00:00:30"/> </binding> </wsHttpBinding> </bindings> </system.serviceModel>
Session Mode Under percall
One of the most important advantages of monotonous services is its ability to save resources and support system scalability. Because the life cycle of a service instance only exists during one call, this method can effectively improve system performance, especially for service instances that hold expensive resources. In addition, when a service instance is destroyed, WCF will not disconnect from the client (through the agent of the client), which consumes much less resources than creating an instance and connection (reference the wayfarer blog)
First, set the service instance to percall.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]class CalculatorService :appledou.Test.WCF.Contract.ICalculator, IDisposable
Sessionmode: Required
Set Service Contract
[ServiceContract(SessionMode = SessionMode.Required)]public interface ICalculator
Client output:
We can see that getresult does not return the value accumulated in the previous two times, because the instance mode is percall.
Server output:
The output from the server can better illustrate the problem. Each method call first creates a service instance (blue font output), and then calls the dispose method to release resources (yellow output ), destroys a service instance when garbage collection is performed. At the same time, we can also see an interesting phenomenon that although a new instance will be created every time a call is made, the sessionid is consistent before the same client proxy is disabled (the sessionid of the previous three-proxy1 is consistent, after three-the sessionid of proxy2 is the same), when the service instance is destroyed, WCF will not disconnect from the client (through the client proxy.
Sessionmode: notallowed
Set Service Contract
[ServiceContract(SessionMode = SessionMode.NotAllowed)]public interface ICalculator
Client output:
Because the service instance is percall, there is no difference with the sessionmode of required.
The server does not have sessionid, and the rest are the same.
Sessionmode: allowed
The difference between allowed and required in sessionmode is that allowed allows a session. That is to say, if it supports the binding of the session, the effect will be the same as that of required. Otherwise, the effect will be the same as that of noallowed. The required must support the binding of the session.
Session mode in persession
Persession can be literally understood as: for each client proxy or session to create an instance, the proxy first calls the service contract operation to create an instance, call the close or terminating method ([operationcontract (isterminating = true)]) to terminate the session and release the service instance. Meanwhile, the service instance can be recycled.
Set the service instance to persession
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]class CalculatorService :appledou.Test.WCF.Contract.ICalculator, IDisposable
Sessionmode: Required
Set Service Contract
[ServiceContract(SessionMode = SessionMode.Required)]public interface ICalculator
Client output:
You can see that the getresult method before the proxy close method is executed returns the value accumulated by the previous two add operations:
Console.WriteLine("The result return via proxy1.GetResult() is : {0}\r\n", proxy1.GetResult());(proxy1 as ICommunicationObject).Close();
Server output:
The server creates an instance when the client calls the add method for the first time, and CALLS dispose to release resources after the close operation is completed. During this period
Sessionid is consistent, indicating that they are executed in the same session.
Sessionmode: notallowed
Set Service Contract
[ServiceContract(SessionMode = SessionMode.NotAllowed)]public interface ICalculator
Client output:
Server output:
Both the server and client are the same as the notallowed of percall. Because the life cycle of a service instance is persession, and the service contract does not allow the session, the life cycle of the service instance is between percall, and there is no sessionid.
But under what circumstances will such a combination be available? Suppose that if the calculatorservice Service implements a service contract and the sessionmode is required or allowed, the instancecontextmode of calculatorservice is persession at this time, and the service contract with sessionmode notallowed will be the same as percall, however, a service contract with the sessionmode required or allowed is a real persession. For example:
The first three methods are called. Each time an object is created and called, the object is released, and the last three calls are within one session. This is because the same service class calculatorservice
Another service contract icalculatorv2 is implemented, and it requires the sessionmode to be required, while the original service contract icalculator
Sessionmode is notallowed:
[ServiceContract(SessionMode = SessionMode.Required)] public interface ICalculatorV2 { [OperationContract(IsOneWay = true, IsInitiating = true)] void Add2(double x); [OperationContract(IsTerminating = false)] double GetResult2(); }
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] class CalculatorService : appledou.Test.WCF.Contract.ICalculator, appledou.Test.WCF.Contract.ICalculatorV2, IDisposable
Client call code:
ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("Calculator");Console.WriteLine("Create a calculator proxy of ICalculatorV1: proxy1");
ICalculator proxy1 = channelFactory.CreateChannel();Console.WriteLine("Invocate proxy1.Add(1)");proxy1.Add(1);Console.WriteLine("Invocate proxy1.Add(2)");proxy1.Add(2);Console.WriteLine("The result return via proxy1.GetResult() is : {0}\r\n", proxy1.GetResult());(proxy1 as ICommunicationObject).Close();ChannelFactory<ICalculatorV2> channelFactory2 = new ChannelFactory<ICalculatorV2>("ICalculatorV2");Console.WriteLine("Create a calculator proxy2 of ICalculatorV2: proxy2");ICalculatorV2 proxy2 = channelFactory2.CreateChannel();Console.WriteLine("Invocate proxy2.Add2(1)");proxy2.Add2(1);Console.WriteLine("Invocate proxy2.Add2(2)");proxy2.Add2(2);Console.WriteLine("The result return via proxy2.GetResult() is : {0}\r\n", proxy2.GetResult2());(proxy2 as ICommunicationObject).Close();
Client output:
Sessionmode: allowed
Similarly, the binding that supports sessions is the same as that of required. The binding that does not support sessions is the same as that of notallowed.
Session mode under single
In single mode, a service is created only once. This mode is easy to understand when the service is opened. Let's take a look at the different scenarios of sessionmode in single mode.
First, set the service instance to single
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]class CalculatorService :appledou.Test.WCF.Contract.ICalculator, IDisposable
Sessionmode: Required
Set Service Contract
[ServiceContract(SessionMode = SessionMode.Required)]public interface ICalculator
Client output:
We can see that after two different proxy calls, the value returned by the server has been accumulating. This indicates that although the client proxy is different, the server calls the same instance.
Server output:
First, after the service is opened, the single-type service model is created, and the sessionid is consistent during the same proxy call.
Sessionmode: notallowed
Set Service Contract
[ServiceContract(SessionMode = SessionMode.NotAllowed)]public interface ICalculator
Client output:
Nothing changed, just like in required Mode
Server output:
The server does not have sessionid as notallowed expects, and the rest are the same.
Sessionmode: allowed
You don't need to talk about this.
Summary
This article is a test based on wshttpbinding. I think it is also applicable to other bindings that support session, such as nettcpbinding. It is hoped that this article will help you clarify the impact of different values between instancecontextmode and sessionmode on the service instance.