session存入Couchbase实现多服务器共享

Posted cathyxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了session存入Couchbase实现多服务器共享相关的知识,希望对你有一定的参考价值。

新建CouchBaseSessionProvider类,继承SessionStateStoreProviderBase类。

public sealed class CouchBaseSessionStateStore : SessionStateStoreProviderBase

private SessionStateSection pConfig = null;
private string eventSource = "CouchBaseSessionStateStore";
private string eventLog = "Application";
private string pApplicationName;


private bool pWriteExceptionsToEventLog = false;
public bool WriteExceptionsToEventLog

get return pWriteExceptionsToEventLog;
set pWriteExceptionsToEventLog = value;

/// <summary>
/// 用于不同请求的Session名称
/// </summary>
public string ApplicationName

get return pApplicationName;

public override void Initialize(string name, NameValueCollection config)

if (config == null)
NLogger.Instance.WriteLog(NLogger.LogLevel.Info, string.Format("Session_Initialize_ex:0", new ArgumentNullException("config")));
//throw new ArgumentNullException("config");
if (name == null || name.Length == 0)
name = "CouchBaseSessionStateStore";
if (String.IsNullOrEmpty(config["description"]))

config.Remove("description");
config.Add("description", "Sample CouchBase Session State Store provider");

base.Initialize(name, config);
pApplicationName = HostingEnvironment.ApplicationVirtualPath;
Configuration cfg = WebConfigurationManager.OpenWebConfiguration(ApplicationName);
//获取配置文件中的<sessionstate>的节点
pConfig = (SessionStateSection)cfg.GetSection("system.web/sessionState");

//写异常的初始化
pWriteExceptionsToEventLog = false;
if (config["writeExceptionToEventLog"] != null)

if (config["writeExceptionToEventLog"].ToUpper() == "TRUE")
pWriteExceptionsToEventLog = true;

public override void Dispose()


public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)

return false;

public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)

string sessItems = Serialize((SessionStateItemCollection)item.Items);

try

var result = CouchBase.Session_bucket.Get<CouchBaseSession>(string.Format("Session_0", id));
var session = result.Value;
if (newItem)

//先删除已存在的项再插入最新的 DELETE FROM Sessions WHERE SessionId = ? AND ApplicationName = ? AND Expires < ?" INSERT INTO Sessions (SessionId, ApplicationName, Created, Expires, LockDate, LockId, Timeout, Locked, SessionItems, Flags)"
if (result.Success)

if (session.SessionId == id && session.ApplicationName == ApplicationName && session.Expires < DateTime.Now)

CouchBase.DeleteSession(session.GetCbKey());


CouchBase.SessionInsert(string.Format("Session_0", id), new CouchBaseSession ApplicationName = ApplicationName, SessionId = id, Created = DateTime.Now, Expires = DateTime.Now.AddMinutes(pConfig.Timeout.TotalMinutes), LockDate = DateTime.Now, LockId = 0, Locked = false, SessionItems = sessItems, Flags = 0 , pConfig.Timeout);

else

//更新以前的项目"UPDATE Sessions SET Expires = ?, SessionItems = ?, Locked = ? WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?"
if (result.Success)

session.SessionId = id;
session.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.TotalMinutes);
session.Locked = false;
session.SessionItems = sessItems;
session.Flags = 0;
session.Timeout = (int)pConfig.Timeout.TotalMinutes;

CouchBase.SessionInsert(session.GetCbKey(), session, pConfig.Timeout);



catch (Exception ex)

NLogger.Instance.WriteLog(NLogger.LogLevel.Info, string.Format("Session_SetAndReleaseItemExclusive_ex:0", ex.ToString()));

public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)

return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actionFlags);

public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)

return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actionFlags);


private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)

SessionStateStoreData item = null;
lockAge = TimeSpan.Zero;
lockId = 0;
locked = false;
actionFlags = 0;
DateTime expires;
// String to hold serialized SessionStateItemCollection.
string serializedItems = "";
// True if a record is found in the database.
bool foundRecord = false;
// True if the returned session item is expired and needs to be deleted.
bool deleteData = false;
// Timeout value from the data store.
int timeout = 60;
try

//1.查询当前session的信息 "SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout FROM Sessions WHERE SessionId = ? AND ApplicationName = ?"
var getresult = CouchBase.Session_bucket.Get<CouchBaseSession>(string.Format("Session_0", id));
var result = getresult.Value;
//如是GetItem的调用则lockRecord为false 如是GetItemExclusive的调用则为true
if (lockRecord)

// "UPDATE Sessions SET Locked = ?, LockDate = ? WHERE SessionId = ? AND ApplicationName = ? AND Locked = ? AND Expires > ?"
//如更新结果为true则locked为false 反之为true
if (getresult.Success)

serializedItems = result.SessionItems;
lockId = result.LockId;
timeout = result.Timeout;
lockAge = DateTime.Now.Subtract(result.LockDate);
actionFlags = (SessionStateActions)result.Flags;
if (result.Expires >= DateTime.Now && result.Locked == false && result.ApplicationName == ApplicationName)

result.SessionId = id;
result.LockDate = DateTime.Now;
result.Locked = true;
result.Flags = 0;
result.Timeout = timeout;
var flag = CouchBase.SessionInsert<CouchBaseSession>(result.GetCbKey(), result, pConfig.Timeout);
if (flag)
locked = false;
else
locked = true;



//2.如查询结果不为空 将查询结果中的值得过期时间与当前时间对比 如是过期 则locked为false deleteData为true 反之 foundRecord为true 并将Session项进行赋值
if (getresult.Success)

if (result.Expires < DateTime.Now)

locked = false;
deleteData = true;

else
foundRecord = true;

//若返回的session已过期 则删除对应项"DELETE FROM Sessions WHERE SessionId = ? AND ApplicationName = ?"
if (deleteData)
CouchBase.DeleteSession(string.Format("Session_0", id));
if (!foundRecord)
locked = false;
//若查询到满足条件的数据并且保留了锁 则设置lockId 并清除actionFlags 并创建SessionStateStoreItem用于返回
if (foundRecord && !locked)

lockId = (int)lockId + 1;
//"UPDATE Sessions SET LockId = ?, Flags = 0 WHERE SessionId = ? AND ApplicationName = ?"
if (actionFlags == SessionStateActions.InitializeItem)
item = CreateNewStoreData(context, timeout);
else
item = Deserialize(context, serializedItems, timeout);


catch (Exception ex)

if (WriteExceptionsToEventLog)

WriteToEventLog(ex, "GetSessionStoreItem");
//throw new ProviderException(ex.Message);

NLogger.Instance.WriteLog(NLogger.LogLevel.Info, string.Format("Session_GetSessionStoreItem_ex:0", ex.ToString()));

return item;

private void WriteToEventLog(Exception ex, string action)

EventLog log = new EventLog();
log.Source = eventSource;
log.Log = eventLog;

string message =
"An exception occurred communicating with the data source.\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + ex.ToString();

log.WriteEntry(message);

public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)

try

//"UPDATE Sessions SET Locked = 0, Expires = ? WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?"
var getresult = CouchBase.Session_bucket.Get<CouchBaseSession>(string.Format("Session_0", id));
var result = getresult.Value;
if (getresult.Success)

result.Locked = false;
result.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.TotalMinutes);
result.SessionId = id;
result.ApplicationName = ApplicationName;

CouchBase.SessionInsert(result.GetCbKey(), result, pConfig.Timeout);


catch (Exception ex)

if (WriteExceptionsToEventLog)

WriteToEventLog(ex, "ReleaseItemExclusive");
//throw new ProviderException(ex.Message);

NLogger.Instance.WriteLog(NLogger.LogLevel.Info, string.Format("Session_ReleaseItemExclusive_ex:0", ex.ToString()));


public override void CreateUninitializedItem(HttpContext context, string id, int timeout)

try

//INSERT INTO Sessions (SessionId, ApplicationName, Created, Expires, LockDate, LockId, Timeout, Locked, SessionItems, Flags) "
CouchBase.SessionInsert(string.Format("Session_0", id), new CouchBaseSession Locked = false, Expires = DateTime.Now.AddMinutes((Double)timeout), SessionId = id, Flags = 1, ApplicationName = ApplicationName, Created = DateTime.Now, LockDate = DateTime.Now, LockId = 0, SessionItems = "", Timeout = timeout , pConfig.Timeout);

catch (Exception ex)

if (WriteExceptionsToEventLog)

WriteToEventLog(ex, "CreateUninitializedItem");
//throw new ProviderException(ex.Message);

NLogger.Instance.WriteLog(NLogger.LogLevel.Info, string.Format("Session_CreateUninitializedItem_ex:0", ex.ToString()));


public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)

try

//DELETE * FROM Sessions WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?"
CouchBase.DeleteSession(string.Format("Session_0", id));

catch (Exception ex)

if (WriteExceptionsToEventLog)

WriteToEventLog(ex, "RemoveItem");
//throw new ProviderException(ex.Message);

NLogger.Instance.WriteLog(NLogger.LogLevel.Info, string.Format("Session_RemoveItem_ex:0", ex.ToString()));



public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)

return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout);

public override void ResetItemTimeout(HttpContext context, string id)

try

//"UPDATE Sessions SET Expires = ? WHERE SessionId = ? AND ApplicationName = ?"
if (CouchBase.Session_bucket.Exists(string.Format("Session_0", id)))

CouchBase.Session_bucket.Touch(string.Format("Session_0", id), pConfig.Timeout);


catch (Exception ex)

if (WriteExceptionsToEventLog)

WriteToEventLog(ex, "ResetItemTimeout");
//throw new ProviderException(ex.Message);
NLogger.Instance.WriteLog(NLogger.LogLevel.Info, string.Format("Session_ResetItemTimeout_ex:0", ex.ToString()));


public override void EndRequest(HttpContext context)


public override void InitializeRequest(HttpContext context)


private SessionStateStoreData Deserialize(HttpContext context, string serializedItems, int timeout)

SessionStateItemCollection SessionItems = new SessionStateItemCollection();
if (!String.IsNullOrWhiteSpace(serializedItems))

MemoryStream ms = new MemoryStream(Convert.FromBase64String(serializedItems));
if (ms.Length > 0)

BinaryReader reader = new BinaryReader(ms);
SessionItems = SessionStateItemCollection.Deserialize(reader);


return new SessionStateStoreData(SessionItems, SessionStateUtility.GetSessionStaticObjects(context), timeout);

private string Serialize(SessionStateItemCollection items)

MemoryStream ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter(ms);
if (items != null)
items.Serialize(writer);
writer.Close();
return Convert.ToBase64String(ms.ToArray());

 

在web.config的<system.web>中加入:

<sessionState cookieless="false" regenerateExpiredSessionId="false" timeout="60" mode="Custom" customProvider="CouchBaseSessionProvider">
<providers>
<add name="CouchBaseSessionProvider" type="guotaigold.WebSite.Component.Framework.CouchBaseSessionStateStore" writeExceptionsToEventLog="false" />
</providers>
</sessionState>

 

以上是关于session存入Couchbase实现多服务器共享的主要内容,如果未能解决你的问题,请参考以下文章

负载均衡session会话保持方法

负载均衡session会话保持方法

PouchDB + Couchbase + Sync Gateway Cookie身份验证

php实现session入库

将token存入session中

由Memcached升级到 Couchbase的 Java 客户端的过程记录