Dino esposito
Wintellect
September 2003
Applicable to: Microsoft® ASP.NET
Summary: Discuss how to implement session status feature in ASP.NET 1.1, and how to optimize session status management in managed web applications. (This article contains some links to English sites.)
table of Contents
Introduction ASP.NET Session Status Overview Synchronous Access Session Status Comparison Status Provider Status Serialization and Defense Sessions Life Cycle Cookieless session
Introduction
In a stateless environment such as a web application, it is not practical to understand the concept of a session state. Despite this, effective status management is a must-have for most web applications. Microsoft® ASP.NET and many other server-side programming environments provide an abstraction layer that allows applications to store persistence data based on each user and each application.
It is important to note that the session status of the web application is the data that caches and retrieves applications in different requests. The session represents all requests sent during connection with the site connection, the session state is a collection of persistent data generated and used during the session. The state of each session is independent of each other, and there is no longer existed at the end of the user session.
There is no correspondence between the session state and any logic entity constituting the HTTP protocol and the specification. The session is an abstraction layer built by a server-side development environment (such as traditional ASP and ASP.NET). ASP.NET display session states and internal implementations of session status depends on the infrastructure of the platform. Therefore, traditional ASP and ASP.NET implement session state in a completely different way, and it is expected to have further improvements and enhancements in the next version of ASP.NET.
This article discusses how to implement session status in ASP.NET 1.1, and how to optimize session status management in managed web applications.
ASP.NET session state overview
The session status is not part of the HTTP infrastructure. That is, there should be a structural component to bind the session state with each incoming request. Runtime Environment (Traditional ASP or ASP.NET) can accept keywords such as session and use it to indicate data blocks stored on the server. To successfully parse the call of the session object, the runtime environment must add a session state to the call context of the requested request. The way to do this varies depending on the platform, but it is the basic operation of the state Web application.
In the traditional ASP, the session status is implemented as the free thread COM object as the ASP.DLL library. (Are you very curious about this? In fact, the CLSID of this object is D97A6DA0-A865-11CF-83AF-00A0C90C2BD8.) This object stores data organized in a name / value to a collection. The "Name" placeholder represents the keywords used to retrieve information, and "value" placeholders represent the content stored in the session state. Name / Value Packets according to the session ID, so that each user see is just the name / value pair he created by himself.
In ASP.NET, the programming interface of the session state is almost the same as the traditional ASP. However, their basic implementation is completely different, and the former is more flexible, scalability and stronger than the latter. Before studying the ASP.NET session state, let us simply review certain structural functions of the ASP.NET session infrastructure.
In ASP.NET, any incoming HTTP request is transmitted via the HTTP module pipe. Each module can be filtered and modified a lot of information carried by the request. The information associated with each request is called "Call Context", which is represented by HTTPContext object in programming. We should not treat the context of the requested context as another container of status information, although it provides the Items collection just a data container. The HTTPContext object is different from all other status objects (for example, session, Application, and Cache) because its limited life cycle exceeds the time required to process the request. When the request is passed through a series of registered HTTP modules, its HTTPContext object will contain a reference to the status object. When the request can be finally processed, the associated call context will be bound to a specific session and a global state object (Application and Cache). The HTTP module responsible for setting each user's session state is sessionStateModule. The structure of the module is designed according to the IHTTPModule interface, which provides a large number of services related to session states for ASP.NET applications. Including generating session ID, cookile session management, retrieving session data from an external status provider, and binding data to a request to call context.
The HTTP module does not store session data internally. The session state is always stored in an external component called "Status provider". The status provider fully encapsulates session status data and communicates with other parts via the ISTATECLIEntManager interface. The session status HTTP module calls the method on the interface to read and save the session state. ASP.NET 1.1 supports three different state providers, as shown in Table 1.
Table 1: Status Client Provider
Provider Description Inproc session values remains active in the memory of the ASP.NET Assist process (ASPNET_WP.EXE or W3WP.exe in Microsoft® Windows ServerTM 2003). This is the default option. The StateServer session value is serialized and stored in the memory of a separate process (ASPNET_STATE.exe). This process can also run on other computers. The SQLServer session value is serialized and stored in the Microsoft® SQL ServerTM table. SQL Server instances can be run locally or run remotely.
The session status HTTP module will read the currently selected status provider from the
The above code actually accesses a copy of the session value created by the HTTP module to read data from a particular status provider (see Figure 1). What if other pages also tries to synchronize the session state? In this case, the current request may stop processing inconsistent data or outdated data. To avoid this, the session status module will implement a reader / writer locking mechanism, and queue the access to the status value. A page with write permissions on the session state will remain locked by the session until the request is terminated. The page can request write permissions for the session state by setting the EnableSsesTate attribute of the @PAGE instruction to True. (This is the default setting). However, the page can also have read-only permissions for session status, for example, when the enablessionState property is set to Readonly. In this case, the module will keep the session's reader lock until the request of the page ends. The result will occur concurrent read. If the page request sets a reader lock, other requests in the same session will not be able to update the session state, but at least read can be read. That is, if the read-only request is currently being processed, the waiting read-only request has higher priority than requests that require full access. If the page request sets a writeer lock, all other pages will be blocked, regardless of whether they are read or written. For example, if there are two frames at the same time that the content is written in the session, a frame must wait until another framework is completed. Comparison status provider By default, the ASP.NET application stores the session status in the memory of the auxiliary process, especially in the dedicated slot of the Cache object. When InProc mode is selected, the session status will be stored in a slot within the Cache object. This slot is marked as a special slot and cannot be accessed by programming. In other words, if all items in the ASP.NET data cache will not return any objects similar to a given session state. The Cache object provides two types of grooves: special slots and common grooves. Programmakers can add and process common slots, but the dedicated slot can only be dedicated by the system (especially the class defined in the System.Web part). The state of each activity session takes up a dedicated slot in the cache. The name of the slot is named according to the session ID, and its value is an instance of the internal unknown class named SessionStateItem. The Inproc status provider obtains the session ID and retrieves the corresponding element in the cache. Then enter the contents of the SessionStateItem object to the HttpSessionState dictionary object and is accessed by the application through the session property. Note that there is an error in the ASP.NET 1.0 that enumerates the dedicated slot of the Cache object to be enumerated. If you run the following code at ASP.NET 1.0, you can enumerate items corresponding to objects included in each current active session state. Foreach (DictionaryEntry Elem in Cache) { Response.write (ELEM.KEY ":" ELM.VALUE.TOSTRING ()); } This error has been resolved in the ASP.NET 1.1, and any system slot will no longer list when you enumerate the cached content. So far, INPROC may be the fastest access option. But remember, the more data stored in the session, the more memory consumed by the web server, which will potentially increase the risk of performance reduction. If you plan to use any process external solution, you should carefully consider the impact of serialization and reverse sequence. Process Solution Use Windows NT Services (ASPNET_STATE.EXE) or SQL Server table to store session values. Therefore, the session status remains outside the ASP.NET assist process, and the additional code layer is required to serialize and reverse sequencing operations between session status and actual storage media. This will occur as long as the request is handled, and the highest optimization must then be performed. Since requesting session data is needed to copy from the external reserve to the local session dictionary, the request has decreased by 15% (external) to 25% (SQL Server). Please note that although this is just a rough estimate, it should be close to the minimum impact, the highest level of impact is much higher than this. In fact, this estimate does not fully take into account the complexity of the type of type actually saved in the session state. In the process of processed storage, the session status survival is longer, making the application's function more powerful because it prevents Microsoft® Internet Information Services (IIS) and ASP.NET fail. By separating the session state with the application phase, you can extend existing applications to the Web Farm and Web Garden architecture. In addition, the session state is stored in an external process, and fundamentally eliminates the risk of periodic data loss due to process cycles. The following describes how to use Windows NT services. As mentioned above, the NT service is a process called ASPNET_STATE.EXE, typically in a C: /Winnt/Microsoft.Net/framework/v1.1.4322 folder. The actual directory depends on the version of Microsoft® .NET Framework you actually run. Before using the status server, ensure that the service is ready to run on a local or remote computer used as a session storage device. The status service is an component of ASP.NET and installs one, so you don't have to run other installer. By default, status services are not running, need to be manually started. The ASP.NET application will immediately try to connect to it after loading the status server. Therefore, the service must be ready and is running, otherwise HTTP exception will be thrown. The figure below shows the properties dialog of the service. Figure 2: Attribute dialog for ASP.NET Status Server The ASP.NET application needs to specify the TCP / IP address of the computer where the session status service is located. You must enter the following settings into the web.config file of the application. Mode = "stateserver" StateConnectionstring = "TCPIP = EXPOWARE: 42424" /> configure> The StateConnectionstring feature contains the IP address of the computer and ports used to perform data exchange. The default computer address is 127.0.0.1 (local host), the default port is 42424. You can also indicate your computer by name. For code, use local or remote computers is completely transparent. Note that non-ASCII characters cannot be used in this name, and the port number is mandatory. If you use processes session storage, session status will still exist and available in future use, regardless of the situation of ASP.NET assist processes. If the service is interrupted, the data will be retained and automatically retrieved when the service is restored. However, if the status provider service is stopped or fails, the data will be lost. If you want the application with powerful features, use SQLServer mode without using the StateServer mode. Mode = "SQLServer" SqlConnectionstring = "Server = 127.0.0.1; UID = configure> You can specify a connection string with the SQLConnectionstring feature. Note that the characteristic string must contain the user ID, password, and server name. It cannot contain tags such as Database and Initial Catalog because this information is default to a fixed name. The user ID and password can replace the integrated security settings. How to create a database? ASP.NET provides two pairs of scripts to configure the database environment. The first pair of scripts are installsqlstate.sql and uninstallsqlstate.sql, and the Session Status NT service is located in the same folder. They create databases and several stored procedures called AspState. However, the data is stored in the SQL Server temporary storage area TEMPDB database. This means that if the SQL Server computer is restarted, the session data will be lost. To resolve this limiter, use the second pair of scripts. The second pair is called InstallPersistSqlState.sql and UninstallPersistSqlState.sql. In this case, an ASPSTATE database will be created, but the data table is created in the same database, and these data tables are also lasting. When installing SQL Server support for a session, you will also create a job to delete expired sessions in the session status database. This job is named aspState_Job_DeleteExpiredSsSions and has been running. Please note that you need to run the SQLServerAgent service normally. No matter which mode you choose, the way to encode the session status operation will not change. You can always work for the Session property and read and write values as usual. The differences in all behaviors are processed on a lower abstraction layer. Status serialization may be the most important difference between session mode. Status serialization and reverse sequence When using internal mode, the object is stored as a live active instance in a session state. If true serialization and reverse sequencing are not generated, you can actually store any object you created in the session (including unsealed objects and COM objects), and the overhead of accessing them will not be too high. If you select the procedure state provider, it is another situation. In the process external architecture, the session value will be copied from the local storage medium (external Appdomain database) to the memory of the AppDomain of the process requested. The task is required to complete the task using the serialization / reverse sequence layer and indicate a major cost of the procedure state provider. This situation is the main impact generated by the code is to store sequentially in session dictionaries. Depending on the data type involved, ASP.NET uses two methods to serialize and deserialize the data. For basic types, ASP.NET uses an optimized internal serialization process; for other types (including objects and user-defined classes), ASP.NET uses the .NET binary formatting program. Basic types include strings, datetime, boolean, bytes, characters, and all digital types. For these types, use tailor-made serialization procedures are faster than using the default .NET binary format. The optimized serialization procedure is not disclosed, nor is also provided in documentation. It is just a binary reader / writer and uses a simple but effective storage architecture. This serialization program writes a byte representation type using the BinaryWriter class, and then writes a byte representing the value corresponding to the type. When reading serialized bytes, this class first extracts a byte to detect the type of data to read, and then call a specific type of READXXX method for the BinaryReader class. Note that the size of the Boolean and digital types is well known, but this is not the case. On the underlying data stream, the string always has a prefix for a fixed length (a 7-bit integer code), and the reader determines the correct size of the string according to this fact. The date value is saved by only the total number of markings that make up the date. Therefore, to perform serialization operations on the session, the date should be an int64 type. As long as you mark the included class marked as a sequentially-sequence class, you can perform serialization operations for more complex objects (and custom objects) using the BinaryFormatter class. All non-basic types are identified by the same type ID and stored with the basic type in the same data stream. In summary, serialization operations can result in performance degradation by 15% to 25%. However, please note that this is based on a rough estimate of the basic type. The more complex the type of use, the greater the overhead. It is difficult to achieve effective session data storage if you don't use a basic type. Therefore, at least in theory, three different string properties of three session slots to save objects are compared to the entire object. However, if you want to serialize the object contains 100 properties, what should I do? Do you want to use 100 slots or use only one slot? In many cases, a better way is to convert complex types into multiple simple types. This method is based on the type converter. "Type Converter" is a lightweight serialization program that returns the key properties of the type in the form of a string collection. Type converters are external classes that are bound to the base class. Decide which properties are saved and how to save. The type converter is also helpful for ViewState storage, which represents a more efficient session storage method than the binary formatter. Session life cycle About ASP.NET session management, it is important to start only when the first project is added to the memory dictionary, the life cycle of the session status object begins. The ASP.NET session can be considered only after executing the following code snippet. Session ["Myslot"] = "Some Data"; The session dictionary typically contains the Object type. To read the data, you need to convert the returned value to a more specific type. String Data = (String) Session ["myslot"]; When the page saves the data to the Session, the value is loaded into the special dictionary that the HttpSessionState class is included. When the current processed request is completed, the contents of the dictionary will be loaded into the status provider. If the session state is empty because the data is not passed in the dictionary, the data is not empty, and more importantly, it is not in the ASP.NET CACHE, SQL Server or NT Status Services. Create a slot to track the current session. This is due to performance reasons, but will have an important impact on the way of processing session ID: a new session ID will be generated for each request until some data is stored in the session dictionary. The HTTP module retrieves the session ID (if it is not a start request), and in the configured status provider is looking for it in the configured state provider. If the data is not returned, the HTTP module will generate a new session ID for the request. This can be easily tested through the following page: <% @ Page language = "c #" trace = "true"%> html> form> body> html> Whenever clicking this button and returns a page, a new session ID will be generated while logging information. Figure 3: Generate a new session ID for each request without using the data stored in the session dictionary. What is the situation of the session_onstart event? Will this event will be triggered for each request? If the application defines the session_onstart handler, the session state is always saved, even if the session state is empty. Therefore, for all requests after the first request, the session ID is always constant. The session_onstart handler is used only if it is indeed necessary. If the session is timeout or abandoned, the session ID does not change when the stateless application is accessed next time. After design, even if the session state expires, the session ID can continue to the browser session. That is, as long as the browser instance is the same, it always uses the same session ID to represent multiple sessions. The session_onend event marks the end of the session and is used to perform all the clear code required to terminate the session. However, please note that only Inproc mode supports the event, that is, the event is only supported when session data is stored in the ASP.NET secondary process. For Session_ONEND events to be triggered, there must be a session status first, which means that some data must be stored in this session state and must be completed at least one request. In InProc mode, the session state added to the cache is given a variable expiration time policy. The variable expiration time indicates that if an item is not used in a certain period of time, it will be deleted. The expiration time of any requested during this period will be reset. The time interval for the session status project is set to a session timeout. The technology used to reset the session state expiration time is very simple and intuitive: the session HTTP module reads only the session status items stored in the ASP.NET Cache. If you know the internal structure of the ASP.NET Cache object, the module will calculate to reset the variable expiration time. Therefore, when the cache project expires, the session has timeout. Expired items will be automatically removed from the cache. The status session module is part of the expiration time policy of this project, also represents a delete callback function. The cache will automatically call the delete function, delete the function and will raise the session_onend event. If the application executes session management through the process outfit, it will never trigger an end event. Cookieles session Each active ASP.NET session is a 120-bit string identified using only characters allowed by the URL. The session ID is generated using a random number generator (RNG) encryption provider. The service provider returns a sequence containing 15 random generated numbers (15 bytes x 8 bits = 120 bits). The random number is then mapped to a valid URL character and returned in a string. The session ID string is sent to the browser and then returns a server application by one of two ways: using cookies (just like in traditional ASP) or modified URL. By default, the session status module will create HTTP cookies on the client, but you can use the modified URL of the embedded session ID string (especially for a browser that does not support the cookie). Which method is used depending on the configuration settings stored in the application's web.config file. To configure session settings, you can use the By default, the cookieless feature is false, indicating that cookies are used. In fact, cookies are just a text file on the web page on the client hard drive. In ASP.NET, cookie is represented by an instance of the HTTPCookie class. Typically, cookie includes name, value collection, and expiration time. When the cookieless feature is set to false, the session status module will actually create a cookie called ASP.NET_SESSIONID and store the session ID. The following pseudo code shows the process of creating a cookie: Httpcookie sessioncookie; SessionCookie = New httpcookie ("ASP.NET_SESSIONID", sessionID); sessioncookie.path = "/"; The expiration time of the session cookie is very short, and the expiration time is updated after each request is successful. The cookie's Expires property represents the expiration time of the cookie on the client. If the session cookie is not explicitly set, the Expires property will default to DateTime.minvalue, that is, the minimum time unit allowed by the .NET Framework. To disable session cookies, set the cookieles feature to TRUE in the configuration file, as shown below: configure> At this point, it is assumed that you request the page at the following URL: http://www.contoso.com/sample.aspx The content of the actual display in the browser address bar will be different, and now contain the session ID, as shown below: http://www.contoso.com/ (5ylg0455mrvws1uz5mmaau45 )/sample.aspx When instantiated a session status HTTP module, the module will check the value of the cookieles feature. If true, the request redirection (HTTP 302) is requested to the modified virtual URL that contains the session ID (before the page name). When the request is processed again, the session ID is included in the request. If the request starts a new session, the HTTP module will generate a new session ID and then redirect the request. If the request is requested, the session ID already exists because the relative URL is used back. The disadvantage of using the cookieless session is that if the absolute URL is called, the session status will be lost. When using cookies, you can clear the address bar, go to other applications, then return to the previous application and retrieve the same session value. If you do this, you will lose the session data when you do this when you disable the session cookie. For example, the following code will interrupt the session: If you need to use an absolute URL, manually add the session ID to the URL by some tips. You can call the ApplyAppPathModifier method for the HTTPRESPONSE class.
href = <% = response.applyapppathmodifier ("/ code / page.aspx")%>> click The ApplyAppPathModifier method will use the string representing the URL and return an absolute URL embedded in session information. For example, this technique is especially useful when you need to redirect from the HTTP page to the HTTPS page. summary The session state is initially introduced by traditional ASP, which is a dictionary-based API that enables developers to store custom data during sessions. In ASP.NET, the session status supports the following two main functions: cookile session ID storage and transmission, and status provider actually stored in session data. To implement these two new features, ASP.NET uses the HTTP module to control the binding between the session state and the processed request context. In traditional ASPs, use session status means using cookies. This is no longer in ASP.NET because you can use a cookieless architecture. With the power of the HTTP module, you can decompose the requested URL to make it contain a session ID and then redirect it. Next, the HTTP module extracts the session ID from the URL and uses it to retrieve any storage. The physical state of the session can be stored in three locations: internal memory, process external memory, and SQL Server tables. Data must be serialized / reverse sequenced processing to be used for applications. The HTTP module copies the session value from the provider to the application's memory at the beginning of the request. After the request is complete, the modified state will return the provider. This data communication will have different degrees of adverse effects on performance, but will greatly enhance reliability and stability, which also makes support for Web Farm and Web Garden architectures more easily. About the Author Dino Esposito is a training teacher and consultant from Rome, Italy. As a member of the Wintellect team, Dino specializes in ASP.NET and ADO.NET, mainly engaged in teaching and consulting in Europe and the United States. In addition, Dino is also responsible for managing Wintelle's ADO.NET courseware, and writing an article for MSDN Magazine's "Cutting Edge" column.