随笔 - 11  文章 - 79  trackbacks - 0
<2010年4月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

欢迎合作

 

联系方式:openhandx@foxmail.com

 

常用链接

留言簿

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

 

 

 

 

 

  OpenHandX-Batch

快速部署手册

 

 

 

 

 

2010-3-23

 

作者:彭明华

openhandx@foxmail.com

 

本文档中的任何部分都不得以任何手段任何形式进行复制与传播

目录

1            前言

2            基本原理

3            总控服务器

4            任务服务器

5            如何向异步批量发起事件


 

1          前言

OpenHandX-Batch异步批量框架的功能在《OpenHandX-Batch企业级批量应用架构.doc》已经说得很清楚,OpenHandX-Batch异步批量架构由7大组件构成,用户可以根据自己的情况选配不同的组件实现热插拔,因此组件的组合非常多。本文就如何快速部署一个标准的企业级批量架构来说明。

2          基本原理

再次重复一下基本原理。



举例说明异步批量的最基本原理,实际应用要比这复杂得多。比如:某企业要生成年终表报,并且年终报表要按照企业的各个部门、分公司出,报表的数据来源有企业的财务系统、ERP系统、CRM系统。

技术分析:

1、              生成报表首先要把数据从各个系统数据库中进行数据抽取、加工、汇总,最终生成报表,每步操作都要按照各个部门、分公司分类

2、              总公司报表要等到各个部门和分公司加工、汇总的数据出来后再汇总,最后生成总公司报表

3、              各个部门和分公司的数据抽取、加工、汇总可以是并行处理的,各个部门和分公司的报表生成可以和总公司的数据汇总并行处理。

批量执行步骤:

由上图可以看出OpenHandX-Batch异步批量框架需要部署总控服务器和任务服务器,为了便于说明,这里所有服务器之间的通讯采用数据库。

3          总控服务器

总控服务器包括本身的配置和节点运行图配置。本身的配置涉及到事件的接收、任务的发送、任务信息的接收、日志的记录。节点图配置是指事件将要做的明细及运行的流程。

首先给异步批量总控服务器和任务服务器创建一个数据库,按照asynBatch.pdm创建表

其次配置节点图,这里创建的树型节点图,主要配置分为4块,以某公司年报表为例:

1、节点图表BT_NODEMAP

NODEMAPID

NAME

PARAMS

TYPE

说明

节点运行图编号

节点运行图名称

预先定义每个节点的任务参数,格式:

参数1=xxx,参数2=xxx

节点运行图类型

0-树型运行图

1-层型运行图

举例

00001

年报表

0

2、节点表BT_NODES

NODEID

PARAMS

WEIGHT

RERUN

NAME

ALIAS

说明

节点编号

预先定义当前节点的任务参数,格式:

参数1=xxx,参数2=xxx

根据节点任务繁重情况设置,越繁重设置值越大,让任务服务器留出更多的资源给此节点,默认为1

重跑模式

0-出错流程退出

1-出错忽略

2-出错重试

对应任务运行服务器配置文件中的节点名称

描述节点的中文名称

举例

00001

1

0

DPT1

部门数据抽取

00002

1

0

DPT2

部门数据汇总

00003

1

0

DPTRPT

部门报表生成

00004

1

0

HQ

总公司数据汇总

00005

1

0

HQRPT

总公司报表生成

3、树型节点关系表BT_TREENODEMAPRELA

RELAID

NODEMAPID

PARENTIDS

TYPE

SOURCEID

说明

关系编号

对应节点图编号,表示关系编号属于哪个节点图

依赖的父关系,格式:

RELAID1RELAID2

关系类型

0-为基本的节点

1-该节点为另一个自节点图

TYPE相关,对应节点编号或节点图编号

举例

00001

00001

0

00001

00002

00001

00001

0

00002

00003

00001

00002

0

00003

00004

00001

00002

0

00004

00005

00001

00004

0

00005

00002的上级是00001表示00002运行必须等到00001运行完成,0000300004运行必须要等到00002运行完成。

4、事件结束最后执行的节点BT_FINYNODERELA

NODEMAPID

ORDERCODE

NODEID

说明

对应节点图编号,表示关系编号属于哪个节点图

则执行的顺序,一般从1开始

对应节点编号

举例

00001

1

CLS

00006节点是FINALLY节点,不管事件的流程执行中是否出现错误都在最后执行,类似Java代码中的

try。。。finally

最后配置总控服务器的配置文件

<?xml version="1.0" encoding="UTF-8"?>

<!--

    批量框架的异步总控配置文件,配置代表调度所依赖的数据信息。调度采用单一JVM运行模式。

    配置内容包括调度数据服务信息。消息交互配置等

   

    开发者: 彭明华

    创建时间:2008-04-30

-->

<configs>

    <controller id="001" acquireRetryDelay="1" waitRetryDelay="20" maxEventCount="5" correspond="false"/>

    <application id="app01" priority="0" persistent="true" loadPersistent="true" description="同一个jvm任务">

配置节点拆分成任务的实现类

配置解析器配置所在的位置,如:在testDB的若干表中

采用树型节点运行图解析器,id="*"表示对所有事件节点图都采用此方案

        <nodeMap id="*" className="open.batch.controller.impl.application.TreeNodeMap" params="source=testDb,nodemaptable=BT_NODEMAP,relatable=BT_TREENODEMAPRELA,nodetable=BT_NODES,finallynodetable=bt_finynoderela">

            <chunk className="open.batch.controller.impl.application.MultiInstanceTreeNodeChunk"/>

配置接收事件的实现类及对应的数据库和表

            <log className="open.batch.controller.impl.application.DBLog" params="source=testDb,eventtable=BT_EVENTSRUNLOG,nodetable=BT_NODESRUNLOG,tasktable=bt_tasksrunlog,tasklog=false,nodelog=true,eventlog=true"/>

配置任务发送的实现类及对应的数据库和表

        </nodeMap>

        <eventReceiver className="open.batch.controller.impl.message.DBEventReceiver" source=" testDb" params="table=BT_EVENTS"/>

        <taskSender className="open.batch.controller.impl.message.DBTaskSender" source="testDb" params="table=bt_tasks"/>

配置任务信息接收的实现类及对应的数据库和表

        <taskReceiver className="open.batch.controller.impl.message.DBTaskReceiver" source="testDb" params="table=bt_taskinfos"/>

        <resource>

配置异步批量用的数据源(数据库)

            <database id="testDb" url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=GBK" driver="com.mysql.jdbc.Driver" username="root" password="111111" maxConnection="20"/>

        </resource>

    </application>

</configs>

配置任务发送的实现类及对应的JMS和队列名

另外:这里举例的配置使用的都是数据库表,也可以使用JMS的实现类

如:

       <taskSender className="open.batch.controller.impl.message.MessageTaskSender" source="pvmsjms" params="queue=task"/>

配置任务信息接收的实现类及对应的JMS和队列名

        <taskReceiver className="open.batch.controller.impl.message.MessageTaskReceiver" source="pvmsjms" params="queue=taskinfo"/>

        <resource>

配置异步批量用的数据源(JMS

            <jms id="pvmsjms" url="tcp://localhost:61616" driver="org.activemq.ActiveMQConnectionFactory"/>

        </resource>

4          任务服务器

任务服务器是具体执行任务的地方,因此它的配置有两个:任务服务器配置、任务的节点配置

任务服务器配置

    <application id="app01" priority="0">

配置任务信息发送的实现类及对应的数据库和表

任务的节点配置文件,可以同时定义多个

        <taskDefineConfig file="taskdefine.xml"/>

        <log className="open.batch.taskserver.impl.run.DBLog" source="testdb" params="table=BT_TASKSRUNLOG"/>

        <taskSenderclassName="open.batch.taskserver.impl.message.DBTaskSender" source="testdb" params="table=bt_taskinfos"/>

配置任务接收的实现类及对应的数据库和表

        <taskReceiverclassName="open.batch.taskserver.impl.message.DBTaskReceiver" source="testdb " params="table=bt_tasks"/>

        <resource>

            <databaseid="testdb" url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=GBK"

                driver="com.mysql.jdbc.Driver" username="root" password="111111" maxConnection="10"/>

            <databaseid="erpdb" url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=GBK"

以下是报表用的数据源,有ERPCRM和报表相关的

                driver="com.mysql.jdbc.Driver" username="root" password="111111" maxConnection="10"/>

        </resource>

            <databaseid="crmdb" url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=GBK"

                driver="com.mysql.jdbc.Driver" username="root" password="111111" maxConnection="10"/>

        </resource>

            <databaseid="reportdb" url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=GBK"

                driver="com.mysql.jdbc.Driver" username="root" password="111111" maxConnection="10"/>

        </resource>

</application>

任务的节点配置(taskdefine.xml

部门数据抽取节点配置

<?xml version="1.0" encoding="UTF-8"?>

<taskDefines>

    <taskDefine name="DPT1" params="">

        <taskRun singleInstance="true" className="open.dpt.Dpt"/>

部门数据汇总节点配置

    </taskDefine>

   

    <taskDefine name="DPT2" params="">

生成部门报表节点配置

        <taskRun singleInstance="true" className=" open.dpt.DptGatHer"/>

    </taskDefine>

    <taskDefine name="DPTRPT" params="">

        <taskRun singleInstance="true" className="open.dpt.DptReport"/>

    </taskDefine>

总公司数据汇总节点配置

   

    <taskDefine name="HQ" params="">

        <taskRun singleInstance="true" className="open.hq.HQGatHer"/>

总公司报表生成节点配置

    </taskDefine>

    <taskDefine name="HQRPT" params="">

        <taskRun singleInstance="true" className="open.hq.HQreport "/>

    </taskDefine>

    <taskDefine name="nullTask"/>

</taskDefines>

注意:总控服务器的BT_NODESname与以上配置的节点名字要一致

5          如何向异步批量发起事件

只要应用程序向BT_EVENTS的表里写入一条数据即发起一个新的事件

事件表BT_EVENTS

ID

EVENTID

PARAMS

CREATETIME

RECTIME

NODEMAPID

说明

事件表的自动编号

应用发起的事件编号或标示,应用通过此号找到已发的事件

定义整个事件的任务参数,格式:

参数1=xxx,参数2=xxx

创建时间

接收时间

节点图编号,与要BT_NODEMAP定义的运行图节点编号一致,不同的编号决定使用不同的节点运行图

举例

[不填]

RPT0001

dtpnum=001;002;003

[当前系统时间]

[不填]

00001

WEIGHT

DESCRIPTION

权重,越大表示该事件的工作越多,让总控服务器留出更多的资源给此事件,默认为1

描述

5

年报表

posted on 2010-04-08 16:12 彭明华 阅读(2782) 评论(13)  编辑  收藏 所属分类: OpenHandX工具

FeedBack:
# re: OpenHandX-Batch1.0 快速部署手册 2010-04-16 10:26 小山羊
今天把AsynBatchConsole部署了,数据为oracle,数据也导入了,配置为
<database id="pvmsdb1" url="jdbc:oracle:thin:@localhost:1521:orcl" driver="oracle.jdbc.driver.OracleDriver" username="root" password="111111" maxConnection="20"/>
<database id="pvmsdb2" url="jdbc:oracle:thin:@localhost:1521:orcl" driver="oracle.jdbc.driver.OracleDriver" username="root" password="111111" maxConnection="20"/>

我选择的是“节点图编辑平台”,登陆成功后,出现以下问题,我跟踪了发现是从缓冲池读取连接时,conn为空,错误如下:
10:21:52,406 INFO [STDOUT] 2010-04-16 10:21:52,406 [http-127.0.0.1-8000-2] ERROR open.batch.console.mapedit.MapEditServlet - MapEditServlet
java.lang.ClassCastException: $Proxy57
at open.database._Connection.getConnection(_Connection.java:38)
at open.database.DatabaseDataSource.getFreeConnection(DatabaseDataSource.java:125)
at open.database.DatabaseDataSource.getConnection(DatabaseDataSource.java:90)
at open.database.DatabaseDataSource.getConnection(DatabaseDataSource.java:76)
at open.batch.console.mapedit.NodeMapDAO.query(NodeMapDAO.java:918)
at open.batch.console.mapedit.NodeMapDAO.queryNodeMap(NodeMapDAO.java:54)
at open.batch.console.mapedit.NodeMapManager.queryNodeMap(NodeMapManager.java:41)
at open.batch.console.mapedit.MapEditServlet.doPost(MapEditServlet.java:187)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at open.batch.console.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Unknown Source)
10:21:52,406 INFO [STDOUT] 2010-04-16 10:21:52,406 [http-127.0.0.1-8000-2] DEBUG open.batch.console.mapedit.MapEditServlet - {"info":"$Proxy57\n","success":false}

  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2010-04-16 10:29 小山羊
以下是我跟踪的问题,到_Connection中就出现错误,
/**
* Returns the conn.
* @return Connection
*/
public Connection getConnection() {
//返回数据库连接conn的接管类,以便截住close方法
Connection conn2 = (Connection)Proxy.newProxyInstance(
conn.getClass().getClassLoader(),
conn.getClass().getInterfaces(),this);
return conn2;
}

不知道是什么原因?  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2010-04-16 11:37 小山羊
调试到
private Connection getFreeConnection(long nTimeout)
throws SQLException
{
Connection conn = null;
synchronized(conns){
for(int i=conns.size()-1;i>=0;i--){
_Connection _conn = conns.get(i);
if(!_conn.isInUse() && _conn.getConnection().isClosed()){
conns.remove(i);
}else if(!_conn.isInUse()){
conn = _conn.getConnection();
_conn.setInUse(true);
break;
}
}
中的if(!_conn.isInUse() && _conn.getConnection().isClosed())判断时开始出现问题
  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2010-04-20 19:58 彭明华
@小山羊
从错误的问题详细信息看,是以下代码出的问题
Connection conn2 = (Connection)Proxy.newProxyInstance(
conn.getClass().getClassLoader(),
conn.getClass().getInterfaces(),this);
可能是oracle驱动版本的问题,换个版本试试  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2010-04-28 08:47 小山羊
能不能提供一个jms得配置文件?  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2010-04-29 11:06 小山羊
在日志中发现的错误:TreeNodeMap read nodeMap error
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null where NODEMAPID='00002'' at line 1
  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2010-05-06 09:07 彭明华
@小山羊
是这句话引起的错误
select * from " + configParams.get("nodemaptable") + " where NODEMAPID=?
由于配置文件的<nodeMap的params属性中没有配置 nodemaptable  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2010-05-06 09:13 彭明华
@小山羊
<jms id="pvmsjms" url="tcp://192.168.1.247:61616" driver="org.activemq.ActiveMQConnectionFactory"/>  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2012-09-17 16:56 wmj2003
upst = cnn.prepareStatement("update " + configParams.get("table") + " set TASKID=TASKID where ID=" + id);  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2012-09-17 16:58 wmj2003
open.batch.taskserver.impl.message.DBTaskReceiver 中getTask()方法的实现有问题,在集群环境中,多台服务器获取任务的是否在插叙的时候锁表呢?  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2012-09-17 17:00 wmj2003
open.batch.taskserver.impl.message.DBTaskReceiver 中getTask()方法的实现有问题,在集群环境中,多台服务器获取任务的时候,是否需要锁表呢?  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2012-10-31 09:19 彭明华
@wmj2003
最近再忙另外一个项目,很少上blog,抱歉.
upst = cnn.prepareStatement("update " + configParams.get("table") + " set TASKID=TASKID where ID=" + id);
就是一个锁表记录操作,锁完后再查询状态RECTIME,就能保证多台服务器获并发时任务不会重复被执行  回复  更多评论
  
# re: OpenHandX-Batch1.0 快速部署手册 2012-11-22 10:29 wmj2003
@彭明华
看明白了,呵呵,我也忘记早给你回复。以前都是通过查询锁表实现的。这也是一种好方法,多交流。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: