摘要:这个文档从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客户端:
?
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的概述:
?
Session Leaks and Diagnosing leaks
Session的泄漏与诊断
?
当一个session没有被返回给池的时候,session泄漏就会发生,这 种情况下,session manager就不能再使用它。因而,当出现一个新的session请求时,session manager不得不创建一个新的session。如果这种情况持续一段时间,很多不可重复使用的session将会被生产,最后DFC会用光 session。所以说找出session泄漏是非常重要的。
?
就像以前提到的,每一个 IDfSessionManager#getSession(...) 都应该伴随IDfSessionManager#release()。一个IDfSession对象不应该保存在不能被肯定释放的地方,因此,把它作为成 员变量或把它存在缓存中都是不明智的。
?
做以下修改以便诊断session泄漏
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.