董爱强,齐志超,冯 扬,张立新
(北京中电普华信息技术有限公司, 北京 100192)
摘 要: 设计了一种Jboss中间件异常事务恢复功能,并实现了maven工程中交易服务的异常事务处理和恢复过程,该过程能在断电、宕机、程序故障等异常情况发生时,及时恢复最近一次正常工作的交易服务状态和数据库数据。并通过日志记录整个异常状态的发生和恢复过程。通过测试证明,该设计与实现是一种有效的中间件异常事务状态恢复的过程,能够为中间件正常运行提供可靠支持和日志依据。
关键词: 中间件;maven工程;交易服务;异常事务;数据恢复
0 引言
中间件作为国网云建设的支持性项目,根据云建设采用的X86集群模式[1],分析了目前采用较多的weblogic等其他类型中间件的利弊。国网公司自主开发的具有自主知识产权的新一代Jboss中间件产品,可以适应云建设和管理的要求,实现集群资源共享,降低成本,提高资源利用率。
在中间件运行期间出现异常事务状态,例如宕机等导致中间件不能正常工作,从而对云平台的使用带来安全隐患。让故障设备尽快恢复到正常状态是本文设计和实现的主要内容。
1 技术背景
1.1 交易服务与恢复
交易服务属于中间件的一个重要功能模块,开启此功能可以处理因异常运行状态产生的中断事务(transaction)。当服务器再次重新启动后,交易服务模块会分析故障前的日志记录,根据日志复原事务现场工作状况,再次提交故障前中断的事务,恢复之前事务和没有保存的数据[2],从而实现对交易的恢复。
1.2 功能设计
交易服务恢复主要两个重要功能模块:事务日志记录和事务恢复的功能。该功能模块需要无缝接入到当前中间件模块中,所以需要实现org.jboss.as.controller.Extension扩展接口。这是中间件启动时加载扩展模块的必要条件。业务在接口的initialize()方法中实现,相当于一个入口方法。为了不影响中间件的启动进程,需要另开一个线程实现业务逻辑,用户获取数据库连接需要读取配置文件。连接分两种:
第一种是用户配置连接信息,程序读取配置信息后创建连接即可;第二种是配置jndi获取连接,通过jndi名获取数据库连接。第二种方式由于获取连接时中间件数据源模块还没加载完成,获取不到连接,此时可设计一个循环等待的过程,直到中间件数据源模块加载完成后才能通过jndi获得连接,然后跳出循环,执行恢复操作。考虑到性能原因,如果jndi数据源本身存在问题,可能永远获取不到,最好设置一个超时参数,表示通过jndi获取数据源的最长等待时间,超出这个时间就直接跳出循环。对于有可能出现重复启动问题,事务会重新提交,要解决这个问题,需要在处理完事务后做结束标记处理,并标记事务是正常提交还是重启服务后的事务提交。对于添加事务日志功能,因为涉及到多线程操作,所以将日志的id以线程id表示。
1.3 数据恢复
数据恢复时,首先需要定义一个TradeExtension类实现org.jboss.as.controller.Extension扩展接口,业务在接口的initialize()方法中实现,为了不影响中间件的启动进程,需要另开一个线程实现业务逻辑,用户获取数据库连接需要读取配置文件,连接分两种。其实现方法与上节的实现方法相同。定义Conn类和ConnManager类主要是读取配置文件获取连接信息,适合单个长事务[3]的恢复。
2 系统启动
2.1 Maven工程构建
中间件中所有的模块都需要构建成maven工程,maven工程构建必须满足特定的条件才能在中间件启动过程中正确加载。jboss中自带maven程序,启动maven工程是第一步工作。
2.2 加载事务模块
中间件启动后需要加载事务模块和处理事务日志。加载模块先执行standealone的启动脚本,执行jboss-modules.jar,然后执行jboss.as.standalone模块,解析此模块的描述文件,执行jboss.as.server的Main类的main方法,此模块调用jboss.as.controller模块解析standalone的配置文件,加载扩展模块,并调用每个扩展模块的扩展接口方法。对于交易模块来说,实现了扩展接口的初始化方法initalize(),此方法中新开启一个子线程处理交易恢复业务。
2.3 处理事务日志
处理事务日志先调用日志工具类的getNearFileName()方法获得离当前时间最近的日志文件,如果此文件不存在,则直接返回,调用getExeSqlList()方法获取所有要执行的记录包含sql语句以及连接信息,遍历每一条记录获取sql语句以及连接信息,创建数据库连接,用sql语句创建事务,然后提交事务。创建文件输出流FileWriter修复每一条执行的记录,最后强制关闭文件流。
2.4 添加事务日志
事务日志记录可实现日志模块配置、日志级别设置、日志轮转设置、日志输出方式配置,并可实现自定义日志扩展。日志管理内容包括执行日志记录、获取模块描述、读取xml文件元素、解析日志元素、解析根日志元素、添加资源属性描述、添加设置参数描述、覆盖服务。
首先定义一个日志类TradeLog,包含的属性有projectName:项目名称,id:日志唯一编号,sql:事务执行的sql语句,result:是事务前日志还是事务后日志,connid:对应数据库连接信息。定义一个处理日志的工具类LogTool,其主要作用是添加日志,初始化日志路径,获得当前日志文件名称(如果当前文件不存在,就会创建当前日志文件),读取距离当前时间最近的日志文件,获取文件中需要执行的sql语句[5]。
2.4.1 日志格式
日志文件名称:yyyymmddhh.log
日志格式:
([a-z]|[A-Z][0-9])*\|[0-9]{1,19}\|([a-z]|[A-Z][0-9])*\|[0-9]{1,10}
([a-z]|[A-Z][0-9])*\|[0-9]{1,19}\|ready-commit
([a-z]|[A-Z][0-9])*\|[0-9]{1,19}\|commit
第一条日志表示事务开始后提交前的日志,后面的日志表示提交后的日志。
日志状态:用户请求数据库操作,如果存在事务开始日志、事务准备提交日志以及事务提交日志,则为正常状态;如果只存在事务开始日志,则不进行恢复操作;如果存在事务开始日志和事务准备提交日志,则进行恢复操作。
日志周期:一个小时生成一个文件。每次读取与当前时间最近的文件。
日志路径:%JBOSS_HOME%\standalone\log\trade_log。
2.4.2 日志添加过程
日志添加,包含事务提交前添加日志和事务提交后添加日志。
事务提交前添加日志,首先定义一个日志类TradeLog,包含的属性有projectName:项目名称,id:日志唯一编号,sql:事务执行的sql语句,result:是事务前日志还是事务后日志,connid:对应数据库连接信息。定义一个处理日志的工具类LogTool,主要作用是添加日志,初始化日志路径,获得当前日志文件名称(如果当前文件不存在,就会创建当前日志文件),读取离当前时间最近的日志文件,获取文件中需要执行的sql语句。
在事务开始后,创建一个Log对象,将要执行的sql语句赋值到Log对象中,将当前线程的id赋值到Log对象的id属性中,创建一个文件输出流FileWriter,用于追加文件信息,将日志信息转化为固定格式的字符串,调用FileWriter的write()方法将这条记录写入到文件中,然后强制关闭文件流。待用户提交事务后,创建Log对象,将当前线程id赋值到id属性中,创建事务结束字符串信息,调用文件输出流将信息追加到文件中。
2.4.3 日志加载类型
用户在添加事务日志时需要添加三种类型的日志,在LogType枚举类型中有定义,分别为START-COMMIT、READY-COMMIT以及DONE-COMMIT。在事务开始后需要添加START-COMMIT类型的日志,此日志主要记录了所要执行的sql集,在事务恢复时执行。在事务准备提交的时候需要添加READY-COMMIT类型的日志,表示此事务准备提交,主要作用是保证事务的原子性。事务提交完成后,添加DONE-COMMIT类型的日志,表示提交完成。
3 事务恢复
中间件可选择是否开启交易服务,开启交易服务后,交易管理器动态监控当前正在执行的交易,并以日志的方式记录在系统中。在全局事务没有完成提交之前,如果系统出现故障,则重启中间件应用服务,交易管理器将根据日志记录的故障发生时交易的状态,不仅仅恢复数据,还要对交易的异常事务进行恢复[4]。事务恢复过程如图1所示。
3.1 实现过程
事务恢复实现过程,首先定义一个TradeExtension类实现org.jboss.as.controller.Extension扩展接口(这是sg-aps启动时加载扩展模块的必要条件),业务在接口的initialize()方法中实现。为了不影响中间件的启动进程,需要另开一个线程实现业务逻辑,用户获取数据库连接需要读取配置文件。连接分两种:第一种是用户配置连接信息,程序读取配置信息后创建连接即可;第二种是配置jndi获取连接,通过jndi名获取数据库连接。第二种方式由于获取连接时中间件数据源模块还没加载完成,肯定获取不到连接,此时设计一个循环等待的过程,直到中间件数据源模块加载完成后才能通过jndi获得连接,然后跳出循环,执行恢复操作。考虑到性能原因,如果jndi数据源本身存在问题,则可能永远获取不到,因此最好设置一个超时参数,表示通过jndi获取数据源的最长等待时间,超出这个时间就直接跳出循环。定义Conn类和ConnManager类主要是读取配置文件获取连接信息。
3.2 日志记录
根据添加日志的方法先添加日志,初始化日志路径,获得当前日志文件名称,读取事务恢复前最近的日志文件,获取文件中需要执行的sql语句,执行该语句恢复数据,生成新的日志记录。默认情况下是在%JBOSS_HOME%\trade_log下,也可自行配置。
4 实现与测试
4.1 构建环境
构建系统测试实现环境,采用junit测试,总共测试4个场景:
(1)maven编译过程;
(2)集成到整个工程的发布过程;
(3)客户端添加日志过程;
(4)中间件重启恢复数据过程。
4.2 交易编译
首先,编译maven工程打开命令窗口,接着进入到模块根目录,再运行mvn celan install。如果命令窗口没有报错,根目录下生成target目录,进入目录可以看到编译好的jar包,如图2所示。
4.3 交易模块发布
首先打开命令窗口,接着进入到aserver根目录,再运行build clean install。在aserver/build/target/目录下生成发布版本,进入到发布版本模块的modules/org/jboss/as/目录下有发布成功的交易模块代码,如图3所示。
4.4 交易日志生成
安装客户端代码后执行代码控制台没有报错,打开到指定的日志目录(目录位置在程序运行时打印出来),有当前日志生成,日志里有一天未完成的事务记录。日志生成界面如图4所示。
4.5 异常事务状态恢复
首先,打开数据库确认日志中未完成的记录不存在,接着在配置文件standalone.xml中添加交易服务,之后运行standalone模式的的启动脚本。打开数据库客户端,查询数据库记录,未完成的记录被添加到数据库中了。图5为数据库恢复前结果,图6为数据库恢复后结果。
以上测试结果初步证明交易服务的恢复功能设计有效可行,在Windows和Linux平台下测试,均能灵活实现跨平台可移植[6]。能够满足国家电网对中间件应用服务器集群数据恢复功能性能等的整体要求。实现便捷在嵌套事务处理上具有一定优势[7],适合云平台建设。
根据国家电网的要求,该设计和实现还需要进一步在安全性[8]和兼容性,大数据压力测试等方面进行进一步的测试,以及与本系统其他功能的联调。在和其他系统联调后,关键功能、性能指标还需多次在不同单位进行测试和评估。
5 结束语
异常事务处理和恢复作为中间件应用服务器的交易服务设计和开发的重要内容,在整个中间件系统的运行中起到了关键作用,为整个中间件的正常运行提供了可靠支持。该功能的稳定性和可靠性直接关系到中间件产品的性能。
本文提供的异常事务状态恢复和管理的设计和实现方式,对中间件这类问题的解决提供了参考和借鉴。
参考文献
[1]冯扬.云安全技术研究.电力信息与通信技术[J].2014,12(1).
[2]魏茂喜,贺贵明,吴元保.事务管理器的事务恢复处理[J]. 微型机与应用,2004,23(4):14-17.
[3]李建,罗军.一种基于工作流的长事务恢复方法的研究[J]. 信息技术,2009(7):152-155.
[4]陈国宁,李陶深,廖国琼.基于Savepoint机制和日志的协作设计事务的恢复方法[J].计算机工程,2004,30(9):58-60.
[5]王耀飞,李林,康卫.实时数据库主动计算的设计与实现[J].电子技术应用,2014,40(8):134-139.
[6]钟舟.对象交易中间件的设计与实现[D].成都:电子科技大学,2008.
[7]肖迎元,刘云生,廖国琼.基于嵌套事务模型的实时数据库系统故障恢复模式[D].武汉:华中科技大学计算机学院,2005.
[8]李珊珊,陈运,姚文斌.基于加密中间件的iSCSI远程镜像方法的研究与实现[J].电子技术应用,2011,37(9):