[MVC Study Notes] 6. Use Memcache + Cookie to solve shared login status in Distributed Systems, mvcmemcache
To solve the bottleneck of Single-host processing and enhance the availability of software, we need to deploy the software on multiple servers to enable multiple second-level subdomains in a frequent manner, deploy websites on independent servers based on business functions, or share multiple channels with a group of servers through Server Load balancer technology (such as DNS polling, Radware, F5, and LVS. After the website program is divided into multiple servers, the Session cannot be synchronously updated across servers due to the limitations of the implementation principle, making it difficult to share the logon status through Session.
We use the MemCache + Cookie solution to solve the problem of shared login status in distributed systems.
The Memcache server itself is a Socket server. Internal data is stored in the memory of the server in the form of key-value pairs. In essence, it is a large hash table. Data deletion adopts the inert deletion mechanism. Although Memcache does not provide the cluster function, it is easy to implement the cluster configuration of Memcache through the client driver.
First, let's briefly introduce the usage of Memcache.
1. Download and install Memcache on Windows)
(1) extract the program to any disk location
Run memcached.exe-d install to install the service. Then, open the service window to check whether the service is successfully installed.
String [] serverlist = {"192.168.1.100: 11211", "192.168.1.101: 11211"}; // initialize the pool for memcache serversSockIOPool pool = SockIOPool. getInstance ("test"); pool. setServers (serverlist); pool. initialize (); mc = new MemcacheClient (); mc. poolName = "test"; mc. enableCompression = false; pool. shutdown (); // close the connection pool
The specific implementation of the solution is as follows:
1. First introduce Memcached. ClientLibrary. dll in the Common layer, and encapsulate the Memcache help class, MemcacheHelper
Using Memcached. clientLibrary; using System; namespace PMS. common {public class MemcacheHelper {private static readonly MemcachedClient Mc = null; static MemcacheHelper () {// it is best to put it in the configuration file string [] serverlist = {"127.0.0.1: 11211 ", "10.0.0.132: 11211"}; // initialize the pool var pool = SockIOPool. getInstance (); pool. setServers (serverlist); pool. initConnections = 3; pool. minConnections = 3; pool. maxConnections = 5; pool. socketConnectTimeout = 1000; pool. socketTimeout = 3000; pool. maintenanceSleep = 30; pool. failover = true; pool. nagle = false; pool. initialize (); // obtain the client instance Mc = new MemcachedClient {EnableCompression = false };} /// <summary> // store data /// </summary> /// <param name = "key"> </param> /// <param name = "value"> </param> // <returns> </returns> public static bool Set (string key, object value) {return Mc. set (key, value);} public static bool Set (string key, object value, DateTime time) {return Mc. set (key, value, time );} /// <summary> /// obtain data /// </summary> /// <param name = "key"> </param> /// <returns> </returns> public static object Get (string key) {return Mc. get (key );} /// <summary> /// Delete /// </summary> /// <param name = "key"> </param> /// <returns> </ returns> public static bool Delete (string key) {return Mc. keyExists (key) & Mc. delete (key );}}}
2. Change the user logon method UserLogin. After the user logs on successfully, a guid is generated. Save the GUID to the Cookie and use the GUID as the key to serialize the login user information to the Memcache server.
Public ActionResult UserLogin () {# region verification code verification var validateCode = Session ["validateCode"]! = Null? Session ["validateCode"]. ToString (): string. Empty; if (string. IsNullOrEmpty (validateCode) return Content ("no: verification code error !! "); Session [" validateCode "] = null; var txtCode = Request [" ValidateCode "]; if (! ValidateCode. Equals (txtCode, StringComparison. InvariantCultureIgnoreCase) return Content ("no: verification code error !! "); # Endregion var userName = Request [" UserName "]; var userPwd = Request [" PassWord "]; // query whether a user has var user = UserService. loadEntities (u => u. userName = userName & u. passWord = userPwd ). firstOrDefault (); if (user = null) return Content ("no: Logon Failed"); // generates a GUID value as the Memache key. var sessionId = Guid. newGuid (). toString (); // store the login user information in Memcache. MemcacheHelper. Set (sessionId, SerializeHelper. SerializeToString (user), DateTime. Now. AddMinutes (20); // return the Memcache key to the browser in the form of a Cookie. Response. Cookies ["sessionId"]. Value = sessionId; return Content ("OK: logon successful ");}
3. Change the OnActionExecuting method of the login verification controller FilterController to read the objects whose Cookie value is the key from the Memcache server:
Protected override void OnActionExecuting (ActionExecutingContext filterContext) {base. onActionExecuting (filterContext); // if (Session ["user"] = null) if (Request. cookies ["sessionId"]! = Null) {var sessionId = Request. cookies ["sessionId"]. value; // check Memcache based on this Value. var obj = MemcacheHelper. get (sessionId); if (obj = null) {filterContext. result = Redirect ("/Login/Index"); return;} var user = SerializeHelper. deserializreceivbject <User> (obj. toString (); LoginUser = user; // simulate the sliding expiration time. memcacheHelper. set (sessionId, obj, DateTime. now. addMinutes (20);} else filterContext. result = Redirect ("/Login/Index ");}