分布式部署工作流引擎如何处理数据源与事务问题
-
数据源和事务问题
本部分介绍用户如何用好BPS的数据源,如何保证用户的事务和BPS引擎事务的一致性,以及BPS的事务分割原理。
本部分包括的内容
BPS数据源:对数据源的使用可以分为基本用法和高级用法,对于基本用法主要通过配置工具进行配置,高级用法可以手工修改配置文件。
基本用法
通过BPS Governor配置数据源
单独使用BPS产品时,如果用户使用的是企业版,可以通过使用BPS Governor中的相应配置功能来配置BPS的数据源。用户可以登录BPS Governor,在”Governor->基本配置->数据源”中配置数据源。下图表示该功能在Governor中的位置。
数据源配置功能如下图。下图为在Tomcat服务器上时的配置界面,Tomcat环境下数据源类型为C3P0并且不可改变;当应用服务器类型不是Tomcat时,数据源类型为”JNDI”,配置项也会有一些不同。
如果用户使用的是开发版,可以登录BPS管理监控工具,在”配置管理->数据源”中配置数据源。配置界面类似于上图所示。
高级用法
手工配置数据源
用户也可以采用手工配置数据源的方式,通过修改对应的配置文件来实现。配置文件的位置:%BPS_HOME%/apps_config/default/user-config.xml。
用户可以在以下节点位置手工修改数据源application/module[name=’ DataSource’]/group[name=’default’]。配置示例如下:
<module name="DataSource">
<!--系统默认数据源配置-->
<group name="default">
<configValue key="Jndi-Name">EOSDefaultDataSource</configValue>
<configValue key="Transaction-Isolation">ISOLATION_READ_COMMITTED</configValue>
<configValue key="Database-Type">DB2</configValue>
<configValue key="Test-Connect-Sql">SELECT count(*y)
from EOS_UNIQUE_TABLE</configValue>
<configValue key="Retry-Connect-Count">-1</configValue>
</group>
...
</module>
BPS API的基本事务规则
BPS API分为两类。一类是只做查询操作,执行过程中没有对数据库的修改动作,为纯查询的API;另一类API在执行过程中会插入、删除或者修改数据库记录,为存在事务操作的API。
纯查询的API因为不对数据库进行更新,所以不会创建新的事务,也不会加入到外部的事务当中。存在事务操作的API需要加入相应的事务处理,处理过程中遵循如下规则:
- 如果BPS API被调用时外部已有事务,则本次BPS API调用不会创建新的事务,而是融合到外部事务当中。如果调用过程中发生异常,则设置事务为MARKED_ROLLBACK状态,并抛出异常。如下图:
- 如果BPS API被调用时外部没有事务,则本次BPS API调用将自动创建新的事务。在API返回时,如果API调用发生异常,则事务回滚,并抛出异常;如果API没有发生异常,则事务提交。如下图:
事务的一致性
在BPS的应用过程中,可能在一个事务中既要处理业务,又要进行BPS调用,下面介绍如何实现这两种调用的一致。
BPS缺省支持的应用服务器产品有 WebSphere、WebLogic、JBoss和Tomcat,可以分成两种情况。
- 如果应用服务器是Tomcat(单纯的WEB容器)
在Tomcat环境下,用户应用的事务和BPS引擎的事务是分离的,每一次BPS调用都是一个独立的事务。 -
如果应用服务器是WebSphere、WebLogic、Jboss
在这几种情况下,BPS使用应用服务器的JTA事务管理。如果用户也使用JTA的事务管理,就可以实现事务的一致性。比如下面的代码,应用的事务和BPS引擎完成工作项的事务是一起的。UserTransaction ut = null;
try {
InitialContext tempCtx = new InitialContext();
ut = (UserTransaction) tempCtx
.lookup("javax.transaction.UserTransaction");
ut.begin();
DataSource dataSource = (DataSource) tempCtx
.lookup("ProductDefaultDataSource");
Connection conn = dataSource.getConnection();
-
/*
* 进行业务操作 ...... 关闭连接
*/
BPSServiceClient client = new BPSServiceClient();
IWFWorkItemManager workitemManager = client.getWorkItemMananger();
workitemManager.finishWorkItem(10001,false);
ut.commit();
} catch (Exception e) {
e.printStackTrace();
if (ut != null)
try{
ut.rollback();
} catch (Exception e1) {
}
}
![]() |
JTA的事务处理规则 如果BPS引擎和应用使用同一个数据源,则可以使用非XA的事务控制。如果应用的数据源和BPS引擎使用的数据源不相同(JNDI地址不相同),则需要使用XA的数据源,才能保证事务的一致性。 |
![]() |
JTA事务 JTA是Java Transaction API(Application Programming Interface)的缩写。 什么是JTA Transaction?它有怎样的特点呢?JTA Transaction是指由J2EE Transaction manager去管理的事务。其最大的特点是调用UserTransaction接口的begin,commit和rollback方法来完成事务范围的界定,事务的提交和回滚。JTA Transaction可以实现同一事务对应不同的数据库,但是它仍然无法实现事务的嵌套。 JTA是只是一组java接口用于描述,J2ee框架中事务管理器与应用程序,资源管理器,以及应用服务器之间的事务通讯。 它主要包括高层接口即面向应用程序的接口;XAResource接口即面向资源的接口;以及事务管理器的接口。值得注意的是JTA只提供了接口,没有具体的实现。 所以,JTA可以处理任何提供符合XA接口的资源。包括:数据库,JMS,商业对象等等 “Java 事务 API”(JTA)启用两阶段提交功能。当配置 WebSphere Application Server等应用服务器以访问数据库时,可选择具有 JTA 能力的驱动程序。如果需要两阶段提交功能,则必须使用启用 JTA 的驱动程序。 只要您在事务中调用了多个数据库连接,就需要 JTA。只要您在事务中调用了多个数据库服务器,就需要两阶段提交。这些连接可以是相同的物理数据库服务器或多个数据库服务器。例如:
如果 Session1 对同一事务内的 Entity1 和 Entity2 调用了方法而这两个企业 Bean 正在使用不同的物理数据库连接,则必须对 Entity1 和 Entity2 使用的数据源启用 JTA。当从相同的数据源对象获取那些连接时,这也是成立的。这需要具有 JTA 能力的驱动程序以提交事务。
如果 Session1 对同一事务(此事务构成一个分布式事务)内的 Entity1 和 Entity2 调用了方法,则必须对 Entity1 和 Entity2 使用的数据源启用 JTA。 |
![]() |
XA事务 简单的说XA事务是遵从XA事务规范的事务。非XA事务是指不遵从XA事务规范的事务。 在谈到XA规范之前,必须首先了解分布式事务处理(Distributed Transaction Processing,DTP)的概念。Transaction,即事务,又称之为交易,指一个程序或程序段,在一个或多个资源如数据库或文件上为完成某些功能的执行过程的集合。 XA与两阶段提交协议 通常情况下,交易中间件与数据库通过XA 接口规范,使用两阶段提交来完成一个全局事务,XA规范的基础是两阶段提交协议。 |
基本概念
BPS API的操作类方法默认都是采用”有则加入,无则创建“的方式(类似于EJB的Required事务策略)加入到外部事务当中的,但有时也有例外。
在一些特定情况下,事务需要以活动为单位,活动执行过后事务即提交;而不是等到API方法执行完毕(外部没有事务),或者依赖于外部的事务提交(外部有事务),这种情况对整个API调用过程来说将会产生”事务分割”。在BPS API中,因为主要以”活动”为单位进行事务分割,所以只有能推动流程流转的API才可能支持事务分割,目前只有以下方法可能支持事务分割:
- 启动流程实例
- 完成工作项
- 完成活动实例
事务分割的的含义:流程调度类型API的执行过程被切分成以”流程启动”或者”活动”为单位的多个分离的事务,也就是在”流程启动”或者”活动执行”完成以后即提交事务,并开始一个新的事务;后面的错误不会回滚以前已经完成的内容。
事务分割生效的控制在两处。第一个是在调用对应API的参数”是否分割事务”的参数;第二个是活动定义中的”分割事务”配置。只有这两个条件都满足,才能在该活动对应的活动实例完成时分割事务,否则不会分割事务。活动定义上的分割事务配置如下图:
事务分割与BPS API的调度过程
下面以finishWorkItem方法为例,来说明事务分割的场景。假定某流程中有三个活动:”填单”(人工活动)、”自动审核”(自动活动)、”人工审核”(人工活动),拓扑顺序如下图。在应用中调用API完成”填单”活动对应的工作项,将会推动流程向前运行,流程执行的基本操作分别为:API开始调用–>完成填单活动–>执行自动审核活动–>启动人工审核活动–>返回。下面分别描述finishWorkItem的参数”是否启动事务分割”为true和false的情况下的执行过程。
- 传入false:即调用finishWorkItem(工作项ID,false)
在这种情况下,调用API方法时传入的”是否启用事务分割”值为false,则按照正常的API执行规则进行调用。不会挂起事务,也不会判断各个活动上配置的”事务分割”配置。
具体完成工作项的过程如下图,该图针对外部有事物的情况,如果外部没有事务,需要在API进入后和退出前分别增加”启动事务”和”提交事务”即可。
-
传入true:即调用finishWorkItem(工作项ID,true)
如果调用API时外部传入的”是否启用事务分割”值为true,则在处理API过程中有以下规则:- 进入API方法时,挂起外部事务,并创建一个新事务;
- 对于流程推进过程中的每一个活动,在结束以后,如果该活动设置了”分割事务”,则执行提交事务,并创建新的事务。
具体完成工作项的过程如下图,这里只描述外部有事务的情况;如果外部没有事务,则去掉挂起或恢复外部事务的步骤即可。
事务分割API过程中发生的异常
在支持事务分割的API执行过程中,如果发生了异常(出现Exception),则会对当前事务进行回滚(Rollback)处理,并中止API的继续执行。具体会回滚到上次启动事务的地方,不会对API外部的事务造成影响(外部的事务仍然能够继续进行和正常提交)。
声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 嗅谱网
转载请注明:转自《分布式部署工作流引擎如何处理数据源与事务问题》
本文地址:http://www.xiupu.net/archives-7022.html
关注公众号:
微信赞赏
支付宝赞赏