利用Tangosol DataCache共享Session的Issue
一.我们知道要共享Session , 必须让两个web Application访问相同的Name=ASP.NET_SessionId的Cookie , 这个Cookie是可以配置在Web.config里面的SessionState 里面的。
Cookie的共享与两个属性有关,一个是Path,另一个是Domain.----如果这个问题不清楚,请参考Cookie工作原理
<sessionState mode="Custom" customProvider="CoherenceSessionProvider" timeout="20" CookieName="kkkk">---可以设置---
<providers>
<add name="CoherenceSessionProvider" type="Tangosol.Web.CoherenceSessionStore, Coherence" cacheName="dist-session-cache"/>
</providers>
</sessionState>
<httpModules>
<add name="CoherenceShutdown" type="Tangosol.Web.CoherenceShutdownModule, Coherence"/>
</httpModules>
ASP.NET_SessionId 是缺省的名称,我们暂且用这个名称。这个Cookie的值就是SessionId.
SessionID的生成是在System.web.dll里面的类SessionIDManager Class 就是调用的一些产生随机种子的计算方法,可以Reflector出来查看。
Implements a cryptographic Random Number Generator (RNG) using the implementation provided by the cryptographic service provider (CSP). This class cannot be inherited.
当一个新的browser打开时,会产生一个新的Session_Cookie,并生成一个SessionId保存到客户端。
如果是有Session_Cookie , 读入判断是否存在。。。。。。。。
二.Tangosol Cache保存的是什么东西呢?
VirtualApplication : SessionId是它的Key,所以我们要共享Session,Key值一定要保持一致,不然在Cache中找不到该Key了。
反编译:Tangosol.Web.CoherenceSessionStore
所以关键的地方就是修改HostingEnvironment.ApplicationVirtualPath
protected static string GetSessionKey(string id)
{
return (HostingEnvironment.ApplicationVirtualPath + ":" + id);
}
而这个System.Hosting. HostingEnvironment是一个常量,不能修改。
一种办法就是继承这个CoherenceSessionStore--provider类,修改这个方法和这个方法有关的方法,另一种方法就是反编译,这个不建议采用的办法,会影响性能。
/////////////////////////////////////////////////////////////////////////
public class CoherenceSessionStoreEx : CoherenceSessionStore
{
#region these two members used to override Coherence Key Generate logic.
private static string GetSessionKeyEx(string sessionId)
{
return ("test"/*TODO: from config*/ + ":" + sessionId);//Test 需要外部配置,在Initalize(…..).这里只是一个实现.
}
protected SessionStateStoreData GetSessionStoreItemEx(HttpContext context, string id)
{
byte[] data = (byte[])this.Cache[GetSessionKeyEx(id)];
if (data == null)
{
return null;
}
SessionStateItemCollection items = Deserialize(data);
if (context == null)
{
return new SessionStateStoreData(items, null, this.Timeout);
}
return new SessionStateStoreData(items, SessionStateUtility.GetSessionStaticObjects(context), this.Timeout);
}
#endregion
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
this.Cache.Insert(GetSessionKeyEx(id), Serialize((SessionStateItemCollection)item.Items), (long)((this.Timeout * 60) * 0x3e8));
}
public override void ResetItemTimeout(HttpContext context, string id)
{
INamedCache cache = this.Cache;
string key = GetSessionKeyEx(id);
cache.Insert(key, cache[key], (long)((this.Timeout * 60) * 0x3e8));
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
this.Cache.Remove(GetSessionKeyEx(id));
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge,
out object lockId, out SessionStateActions actions)
{
SessionStateStoreData data = this.GetSessionStoreItemEx(context, id);
locked = data != null;
lockAge = TimeSpan.Zero;
lockId = Guid.NewGuid();
actions = SessionStateActions.None;
return data;
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
out SessionStateActions actions)
{
locked = false;
lockAge = TimeSpan.Zero;
lockId = null;
actions = SessionStateActions.None;
return this.GetSessionStoreItemEx(context, id);
}
}
另:
如果是不同的机器上,WebApplication一样,都是在一个Domain,那么Tangosol就不用修改任何配置,就可以支持farm Session Share.
我们这里解决的是ASP.NET Web applications共享Session的问题,但是必须要让Session Cookie能够共享。