首页 » 技术分享 » DFC Session Management 白皮书

DFC Session Management 白皮书

 

DFC Session Management
Srinivas Jakkula


摘要:这个文档从application出发,介绍DFC Session Management的使用细节

 

DFC Session 和 Session Manager总揽

 

DFC Session 赋予指定用户访问指定repository的权利。这意味着一个DFC Session 负责一个客户端与 repository连接的凭证。一个 Sessio对象就是一个IDfSession接口的实例。几乎所有的通过DFC访问 repository的功能都需要一个 repository(DMCL) sessio,DFC session 包括 repository session.DFC客户端通过Session Manager获取一个session对象。

 

Session Manager管理一个或多个 repository的sessions. Session Manager 被客户端程序用来获取 Session,并在 Session使用完后释放 Session。 Session Manager 同时维护DMCL Session的连接池,当有 Session请求时把他们分配给DFC Sessions. DFC Session应该通过 Session Manager获取而不是直接通过IDfClient对象获取。

 

Session Manager提供一些方法以便让DFC客户端:

  • 管理 存储/访问 认证
  • 认证用户访问
  • 请求和释放sessions
  • 处理事务
  • 认证用户
  • 统计session
  • 捕捉异常(checked and unchecked)


 

Session Manager和 Session Pooling

 

为了减少创建和销毁 repository sessions的开销, Session Manager使用DMCL( repository ) session池来更有效的处理sessions。 Session Manager 维护一个DMCL Session的连接池。当你释放一个从 Session Manager获取的session时, Session Manager会等待一段时间才真正的断开这个连接。 在这个旧的连接断开之前, 如果你用 Session Manager向同一个 repository 请求获取 Sessio,你将得到这个旧的

,这样就节省了重新获取你登陆信息并创建一个新session的开销。如果旧的那个已经断开了,或者你希望得到一个新的session,或者得到连接其他 repository 的session, Session Manager会给静默的为你获取一个新的session.

 

如果连接池被关掉了, Session Manager还是可以正常使用的,只不过效率很低.你可以使用IDfSessionManager接口的getSession或newSession方法通过 Session Manager获取session.假设连接池存在可获取的session的话,getSession会获取这个session,否则就创建新的session。 getSession得到的 共享session减少应用程序使用的资源。但这样做并不总是线程安全的。

 

应该注意DFC pooling 和 DMCL pooling是有区别的,释放DfSession不会让dmcl立刻断开连接,而是在这个连接实效一段时间后。

 


Transaction Handling

 

因为 Session Manager能够同时处理多个repository的session,他也支持多个repository的事务处理。他一直绑定在每个repository的底层关系数据库的事务上。但是不支持嵌套事务。

 

Session Manager事务不使用二次提交算法,它们绑定在底层数据库的事务工程里。这样的结果就是,多repository的事务,即使其中的1个repository的使用已经提交了,这个事务还是允许失败的。比如,有3个 repository,前2个的事务已经被成功的提交了,但是第三个没有, Session Manager不能回滚前2个已经成功提交的事务。

 

Session Transaction 和Session Manager Transaction是不同的。IDfSession 接口有 beginTrans方法来于数据库的事务通讯。所有的变更操作都不会被提交到repository 直到commitTrans 方法被调用。你可以使用abortTrans方法来撤销数据库的事务。

 

IDfSessionManager的beginTransaction方法用于开始Session manager事务,这个方法会生成一个新的受管事务。只有在 beginTransaction被调用之后获取的session才可以被这个事务管理。在这之前获取的Session对象不会被这个事务管理。commitTransaction 用来提交事务, abortTransaction用来撤销事务。

 

Lifecycle of DFC Client Application

DFC客户端应用程序的生命周期

 

虽然每一个 DFC客户端应用程序都有不同的功能,复杂程度也取决于客户需求,但是他们连接repository以完成特定的功能的步骤还是相同的。以下是典型的 DFC客户端处理session的概述:

 

  1. 获取一个 DFC客户端对象
  2. 取得Session Manager一个新的实例
  3. 通过Session Manager注册用户的repository访问权限
  4. 取得DFC session用以和repository工作
  5. 执行业务功能
  6. session 释放回 Session Manager
  7. 销毁或终止Session Manager

Session Leaks and Diagnosing leaks

Session的泄漏与诊断

 

当一个session没有被返回给池的时候,session泄漏就会发生,这种情况下,session manager就不能再使用它。因而,当出现一个新的session请求时,session manager不得不创建一个新的session。如果这种情况持续一段时间,很多不可重复使用的session将会被生产,最后DFC会用光session。所以说找出session泄漏是非常重要的。

 

就像以前提到的,每一个 IDfSessionManager#getSession(...) 都应该伴随IDfSessionManager#release()。一个IDfSession对象不应该保存在不能被肯定释放的地方,因此,把它作为成员变量或把它存在缓存中都是不明智的。

 

做以下修改以便诊断session泄漏

  1. 打开$DOCUMENTUM/config/dfc.properties文件,在我们的机器上它在c:/Documentum/config文件夹下。
  2. 加上这行dfc.resources.diagnostics.enabled=true .
  3. 保存并关闭dfc.properties
  4. 打开$DOCUMENTUM/config文件夹下的log4j.properties文件,在最后加上下边的内容。这些内容会直接被写进sessLeakDetector.log.

For DFC 5.2.5 SPx 
================= 
 
log4j.logger.com.documentum.fc.client.DfSessionLeakChecker=
ERROR,SESS_LEAK_DETECT 
log4j.appender.SESS_LEAK_DETECT=org.apache.log4j.RollingFil
eAppender 
log4j.appender.SESS_LEAK_DETECT.File=C/:/Documentum/logs/se
ssLeakDetector.log 
log4j.appender.SESS_LEAK_DETECT.MaxFileSize=100MB 
log4j.appender.SESS_LEAK_DETECT.MaxBackupIndex=5 
log4j.appender.SESS_LEAK_DETECT.layout=org.apache.log4j.Pat
ternLayout 
log4j.appender.SESS_LEAK_DETECT.layout.ConversionPattern=%d
{ABSOLUTE} [%t] %m%n 
 
For DFC 5.3 and Higher 
====================== 
 
log4j.logger.com.documentum.fc.client.DfSessionManagerPool=
DEBUG,SESS_LEAK_DETECT 
log4j.logger.com.documentum.fc.client.DfSessionmanager=DEBU
G,SESS_LEAK_DETECT 
log4j.logger.com.documentum.fc.client.DfDisposableCollectio
n=DEBUG,SESS_LEAK_DETECT 
log4j.appender.SESS_LEAK_DETECT=org.apache.log4j.RollingFil
eAppender 
log4j.appender.SESS_LEAK_DETECT.File=C/:/Documentum/logs/se
ssLeakDetector.log 
log4j.appender.SESS_LEAK_DETECT.MaxFileSize=100MB 
log4j.appender.SESS_LEAK_DETECT.MaxBackupIndex=5 
log4j.appender.SESS_LEAK_DETECT.layout=org.apache.log4j.Pat
ternLayout 
log4j.appender.SESS_LEAK_DETECT.layout.ConversionPattern=%d
{ABSOLUTE} [%t] %m%n

下边是提供一个session泄漏的例子,它将告诉你泄漏具体发生在哪个类中,

  15:09:38,803 [Resource Housekeeper] DFC_BOF_SESSION_LEAK| Unreleased session found in  finalize "docbase=wdk52no, refCounter=2, transFlag=false  Session
=com.documentum.fc.client.DfSession@19ee8a".
com.documentum.fc.client.DfSessionLeakException
 at
com.documentum.fc.client.DfSessionLeakChecker.<init>(DfSessionManager.j
ava:1186)
 at
com.documentum.fc.client.DfSessionManager.createRequiredSessionObject(D
fSessionManager.java:513)
 at
com.documentum.fc.client.DfSessionManager.getSession(DfSessionManager.j
ava:507)
 at
com.documentum.fc.client.DfSessionManager.getSession(DfSessionManager.j
ava:283)
 at
com.documentum.custom.test.TestDFCDiag.onClickHello(TestDFCDiag.java:41
)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.ja
va:39)
 at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccesso
rImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:324)
 at
com.documentum.web.form.FormProcessor.doInvokeMethod(FormProcessor.java
:1168)
 at
com.documentum.web.form.FormProcessor.invokeMethod(FormProcessor.java:9
38)
 at
com.documentum.web.form.FormProcessor.fireActionEvent(FormProcessor.jav
a:769)
 at
com.documentum.web.form.RecallOperation.execute(RecallOperation.java:98
)
 at
com.documentum.web.form.FormProcessor.openForm(FormProcessor.java:136)
 at
com.documentum.web.form.WebformTag.doStartTag(WebformTag.java:125)
 at
org.apache.jsp.testDFCDiag_jsp._jspx_meth_dmf_webform_0(testDFCDiag_jsp
.java:69)
 at
org.apache.jsp.testDFCDiag_jsp._jspService(testDFCDiag_jsp.java:46)
 at
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:137)
        ......
 
This mode is used to diagnose session related issues. It can impact performance and should be preferably
used on development/test systems instead of production systems. 


SessionListener


在DFC中,你可以开发一个实现IDfSessionManagerEventListener接口的session listener类来捕获session创建和销毁。 IDfSessionManagerEventListener接口有2个需要实现的方法:onSessionCreate 和 onSessionDestroy。

 

一旦你有了session listener类,你需要把使用IDfSessionManager.setListener(…) 方法把这个类作为listener注册到sessionmanager。

 

下边是简单的session listener的实现,它用于打印出每一次session的产生和销毁。

 

static class SessionListenerImpl implements IDfSessionManagerEventListener
    {
        public void onSessionCreate(IDfSession sess) throws DfException {
            System.out.println("Session created: "  + sess.getSessionId());
            
        }
 
        public void onSessionDestroy(IDfSession sess) throws DfException {
            System.out.println("Session Destroyed: " + sess.getSessionId());
        }
        
    }
 

Orphaned Objects

孤立对象

 

孤立对象是从已经被释放回DFC session manager的session获取的对象。对这种对象的探测的技术是DFC5.3被加入的。通过开启DFC session诊断来实现对孤立对象的探测。如果对象在多线程程序中分发,事情就更加复杂。记住,如果session已经被释放了但是对象还需要被分发,你应该传送IDfid然后使用这个id通过IDfSession.getObjectById(…)方法来重新回去对象。

 

DFC sessions and WDK Applications

 

在WDK工程中,只存在一个IDfSessionManager的实例。你可以通过SessionManagerHttpBinding.getSessionManager()方法来获取 IDfSessionManager的引用。在wdk程序中取得一个新sessionmanager是不明智的。同样,当你在WDK程序中需要IDfSession,应该使用Component中的getDfSession方法而不是在session manager中获取一个session。这样component就会负责这个session的回收而不用你显示的回收。通过session得到对象,它的生命应该很短暂并且应该只存活于一个request/response范围。SysObject不应该比一个 request/response持久,并且创建这个对象的底层session应该被断开。正确的做法是像上一节说的那样,只保持object id,需要 SysObject的时候再去重新获取它。

 

到底该怎样做呢?

 

1 如何获取一个DFCsession并把它释放回池

 

参考以下代码片段


          //create Client objects
          IDfClientX clientx = new DfClientX();
          IDfClient client = clientx.getLocalClient();

        
          //create a Session Manager object
          IDfSessionManager sMgr = client.newSessionManager();
        
          //create an IDfLoginInfo object for user creddentials
          IDfLoginInfo loginInfoObj = clientx.getLoginInfo();
          loginInfoObj.setUser(<user>);
          loginInfoObj.setPassword(<pass>);
          loginInfoObj.setDomain(null);
 
          //bind the Session Manager to the login info
          sMgr.setIdentity(<docbase>, loginInfoObj);
 
 
          IDfSession session = null;
 
          try {
             //get the IDFsession instance by using getSession or newSession
               Session = sMgr.getSession(<docbase>);
 
                //user the session to perform repository functions
                 ……….
                 ……….
 
              }finally{
                 //release the session
                  sMgr.release(session);
              }
 


2 如何把一个用户的访问认证转发给所有repositories?

 

在以上代码中,把 sMgr.setIdentity(<docbase>, loginInfoObj); 替换为sMgr.setIdentity( * , loginInfoObj );

 

3 如何获取一个新的session而不是从池中取得?

 

使用 IDfSessionManager的呢newSession方法而,不使用getSession方法。

 

4 如何在session manager中关闭连接池?

 

在dmcl.ini中,把‘connect_pooling_enabled’属性设为‘F’,这样每次需要session的时候,一个新的session就会被创建了。

 

5 如何让DFC释放session后立刻断开DMCLsession?

 

在客户程序的JVM启动脚本中,加入‘DebugSessionManager’选项,这样 DFC释放session后立刻断开DMCLsession,而且session超时后也自动断开。就像这个选项说明的,这是一个Debug参数,不推荐在production程序上使用( 影响性能)。

 

6-9对DMCL sessions有效,对IDfSessionManager没有意义

 

6 如何配置DMCL session的timeout?

 

默认 DMCL session timeout时间是5分钟。可以修改server.ini的‘client_session_timeout’来重设定。(重启server生效)

 

7 如何限定每个 DMCL session被重复利用的次数?

 

修改dmcl.ini 中的‘connect_recycle_interval’。这样做会保持一个单独的session不会变的很大。默认值是1000.

 

8 如何限定一个客户端在一个repository中的session的最大数目?

 

这个每个客户端默认允许有10个session。可以修改dmcl.ini中的max_session_count (重启server生效)。

 

9 如何设置一个repository中同时存在的 session的 最大数目?


修改 server.ini的 concurrent_sessions (重启server生效)。默认是100个.


10 如何处理事务?

 

可以使用Session manager的事务功能来处理事务。下面代码片段是一个使用事务的模板。记得,只有在beginTransaction后获取的session才会被这个事务管理。

 

try {
    //start the transaction  
  sMgr.beginTransaction();
 
    //get the session
  session = sMgr.getSession(docbase);
 
  //perform actions
  …….
 
    //commit the transaction
  sMgr.commitTransaction();
 
 }catch(exception ex){
  //handle exception
  ……

    //abort the transaction
  sMgr.abortTransaction();
 }finally{
    //release the session
  sMgr.release(session);
 }

 


11 如何启用session诊断

 

在dfc.properties中加入‘dfc.resources.diagnostics.enabled=true ‘.


12 DFC Session是线程安全的么?

 

从DFC4.2.7开始,所有对IDfSession 和 IDfSessionManager的调用都是同步的,因此是线程安全的。

 

13 如何在DFC中判断一个session是存活的或是超时的?

 

没招...IDfSession.isConnected只在IDfSession.disconnect()被调用后才有用处,否则不管这个session是活的还是过期的,它都会返回TRUE。

 


14 在component中应该调用idfsession. beginTrans() 还是 sMgr.beginTransaction()?

 

调用 idfsession. beginTrans()的话,你会得到异常

DfException:: THREAD: [ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.De
fault (self-tuning)'; MSG: [DM_DFC_E_INVALID_OPER_ON_MANAGED_SESSION] Invalid op
eration on a managed session. Operation should be performed using the session ma
nager.; ERRORCODE: 406; NEXT: null

所以不得不使用 sMgr.beginTransaction(),虽然这会产生另外一个的session


what if I use idfsession.beginTrans() but not sMgr.beginTransaction() in my component class?

You will get an excpetion as above,that means you must use Session Manager to open a transaction,even it need another session difference from current one.

 






转载自原文链接, 如需删除请联系管理员。

原文链接:DFC Session Management 白皮书,转载请注明来源!

0