2011年10月15日星期六

datasnap的初步 Session的管理

Datasnap的session管理是强制的,没有选项能说不要。
管理靠一单例TDSSessionManager来管理。对于目前说到TDSTCPServerTransport,建立的的Session为TDSTCPSession,它是TDSSession的子类。

Session在开始连接后,就创建了,再连接断开后消亡。
 TDSSession = class
  private
    FStartDateTime: TDateTime;   /// creation timestamp
    FDuration: Integer;          /// in miliseconds, 0 for infinite (default)
    FStatus: TDSSessionStatus;   /// default idle
    FLastActivity: Cardinal;     /// timestamp of the last activity on this session
    FUserName: String;           /// user name that was authenticated with this session
    FSessionName: String;        /// session name, may be internally generated, exposed to 3rd party
    FMetaData: TDictionary; /// map of metadata stored in the session
    FMetaObjects: TDictionary; /// map of objects stored in the session
    FUserRoles: TStrings;        /// user roles defined through authentication
    FCache: TDSSessionCache;
    FLastResultStream: TObject;  /// Allow any object which owns a stream, or the stream itself, to be stored here
    FCreator: TObject;           /// Creator of the session object reference
可以看出,Session可以用存储了很多东西 。用得多的是FMetaData与FMetaObjects
对于字符串,PutData放进去,GetData取出来;对于Object,PutObject放进去,GetObject取出来。
使用方法为
TDSSessionManager.GetThreadSession.PutData('userid', userId);
userId := TDSSessionManager.GetThreadSession.GetData('userid');
另外,放入FMetaObjects的Object,Session的Free时,会自动帮忙Free,所以不必自己去Free的。

关于Session的超时,
这里自然就想到了TDSTCPServerTransport的KeepAliveInterval和KeepAliveTime属性,这两个属性,其实和Session管理没关系。
跟踪代码,这两个属性的反应在IdStackWindows.pas的
procedure TIdStackWindows.SetKeepAliveValues(ASocket: TIdStackSocketHandle;
  const AEnabled: Boolean; const ATimeMS, AInterval: Integer);
var
  ka: tcp_keepalive;
  Bytes: DWORD;
begin
  // SIO_KEEPALIVE_VALS is supported on Win2K+ only
  if AEnabled and (Win32MajorVersion >= 5) then
  begin
    ka.onoff := 1;
    ka.keepalivetime := ATimeMS;
    ka.keepaliveinterval := AInterval;
    WSAIoctl(ASocket, SIO_KEEPALIVE_VALS, @ka, SizeOf(ka), nil, 0, @Bytes, nil, nil);
  end else begin
    SetSocketOption(ASocket, Id_SOL_SOCKET, Id_SO_KEEPALIVE, iif(AEnabled, 1, 0));
  end;
end;

里,其实就是简单设置了一下socket fd的属性,所以说TDSSessionManager毛关系都没有。

另外, KeepAliveTime默认值为300000,也就是300秒,KeepAliveInterval默认值为100,这是啥意思呢。KeepAliveTime是sockfd最后一次通讯后,等待了的时间,如果300秒内没通讯,socket栈就自己开始发送心跳探测了,如果每次都没回答,就每隔KeepAliveInterval毫秒问一次。至于问多少次认为是网络断开了,根据Windows OS来定的,windows 2000, 2003是5次,vista以后问10次。也就是说,根据TDSTCPServerTransport的默认设定,网络断了,在win7上,要300+0.1*10,也即是301秒才知道网络断了。
OS的系统设定更长,没数据通讯后2小时才开始探测,每隔1秒探测一回。
SIO_KEEPALIVE_VALS值Windows的OS独有的,Unix还是用SO_KEEPALIVE。

跑题远了,回到正题。如何监控Session呢,TDSSessionManager提供了方法给你插入监听事件。
上代码
var
  event: TDSSessionEvent;

initialization
  event := procedure(Sender: TObject;
            const EventType: TDSSessionEventType;
            const Session: TDSSession)
  begin
    case EventType of
      SessionCreate:
        begin
          LogInfo('SessionCreate');
          LogInfo(Format('SessionName=%s', [Session.SessionName]));
        end;
      SessionClose:
        begin
          LogInfo('SessionClose');
          LogInfo(Format('SessionName=%s', [Session.SessionName]));
        end;
    end;
  end;
  TDSSessionManager.Instance.AddSessionEvent(event);
finalization
  TDSSessionManager.Instance.RemoveSessionEvent(event);

这样就可以了,有多少事件都可以插入监听。


没有评论:

发表评论