应用系统批处理模块的架构设计要点
最近的一个系统模块遇到了性能瓶颈,调查后发现它有许多批处理任务,大批量处理的情况下,会导致联机交易的性能告警问题。
很容易就能决定使用批处理框架进行隔离,但是spring batch这种标准批处理框架封装的非常好了,却还要关注许多原理性的问题。
并且,在真实的上线环境中,不能光考虑应用功能的实现,还需要考虑一系列其它问题。
例如批处理的日志问题,大量的日志记录,可能会造成日志文件系统告警,因为生产上日志文件系统都是有一个大小限制的,除非不是写日志文件,而是改为公共模块平台发送消息。
这可能是非常细节的一些情况。
本文不会深入spring batch的技术细节,而是从整体原理,需要关注的设计要点等方面,进行介绍,目的是建立一个批处理模块实际上线运行的模块框架。
什么是批处理?
按照JCP的JSR352(Batch Applications for the java platform)中的定义,批处理是一种非交互型、后台运行的处理大量数据的处理模式。
批处理适用场景
批处理模式适用于实时性、交互性要求不高,待处理数据量较大的场景。这些场景往往有如下的特点:
-
无用户交互的自动化批量数据处理。典型的是基于时间的事件,月终的计算、通知等。
-
周期性的重复处理。例如保险收益计算以及利率调整,银行的利息结算等。
-
内外部系统数据信息整合。
那么一般来说,应用程序中需要写一个后台线程处理的任务,都可以放在批处理框架里。
例如从一个文件读取数据到数据库,从数据库读取数据处理计算后再写入数据库或者发出异步通知等,都可以使用批处理框架。
批处理标准范式
经过多年的发展,尤其是SpringBatch的应用,已经形成了批处理框架的标准范式:
批处理架构设计要点
我们在进行应用模块落地实施的时候,需要考虑非常多的技术要点。例如,集群计算资源弹性管理,任务调度、分发、执行等全生命周期管理,异常处理与告警通知管理,表数据归档与清理管理,业务文件清理管理,静态配置管理,对批量业务作业全生命周期的进行配置,管理与监控……等等。
我们下文尝试分层次较大粒度来梳理一下,批处理应用的一些关注点。
1
应用层
Java领域的批处理框架,最为经典的就是Spring batch,我们不再考虑具体的技术细节,只是探讨训词关注的问题,以及可能的应对方案。
批处理框架
但是我们需要考虑如下的几个点:
-
任务调度。Spring batch这种批处理框架,往往需要与任务调度框架结合使用,例如开源的Quartz。
-
任务并行。面向大数据量的处理,Spring batch也提供了任务并行处理的方式,以加快处理效能。
-
异常处理。在执行任务异常时,是需要skip还是需要中断,或者告警?都需要根据业务场景设计好。
-
任务超时。尤其是通过RPC调用其它模块的的时候,有可能超时后的处理。
-
内存溢出。如果生产者无休止的请求服务,可能会导致内存崩溃,可以使用有界的数组阻塞队列ArrayBlockingQueue等,匀速处理任务,最终做到内存使用可控。
-
重复执行。如果设置了重复执行策略,不能无休止的占用资源,需要有终止策略及告警措施。
并行拉取数据
在数据库数据处理场景,可以通过Springbatch的并行处理机制,结合第二部分的MyBatis的模式,来进行数据处理。
甚至可以考虑,从数据库大批量的数据读,进行读写分离,防止影响联机交易。
线程隔离
另外一篇文章介绍。
日志文件系统容量
批处理任务处理的数据量较大,如果直接记录文件系统里面的日志文件,需要考虑容量,归档措施。
数据激增
批处理的数据是否会在某个时间段激增,批处理的时间过长,极端情况下会技术不超时,但是业务超时,以及占用的CPU资源、IO资源等居高不下。
这种情况下,需要考虑削峰填谷的手段,或者动态增加线程处理资源,结合线程隔离的手段,进行
批处理后动作
批处理后,我们往往有更新数据库或者向外发送通知等动作,要进行异步化,防止阻塞。
2
数据层
IO
批处理面向的源数据有两种情况,一种是读取文件,一种是读取数据库。
如果是读取数据库,一次读取一条记录的话,将会导致非常大的网络IO消耗,以及处理耗时。
所以,要增加并行处理能力,减少耗时。上面提到过可以通过并行查询的方式来做到。
同时,如果有对数据库的操作,可以应用ORM框架的能力。
ORM框架-MyBatis
-
批量处理 & 及可能的数据包过大的问题
MyBatis框架,本身支持批量插入、批量更新等功能。
需要注意的是,数据量过大的情况下,由于一次发送包的大小有限制,数据库一次处理的大小也有限制,因此引用层也需要控制好大小的问题。 -
与Spring Batch结合
MyBatis本身提供了MyBatisPagingItemReader,MyBatisBatchItemWriter的处理器。
结合Spring Batch的chunk处理机制,可以提升批处理效率。
数据库
到了数据库层,需要考虑的就是超出了数据库单表推荐限制的情况下,要做一系列的处理。
-
分库分表
这种情况下,需要注意,就像给表建立索引一样,分库分表的处理,也要有区分度,否则意义并不大。
例如一个应用总用户数量百万量级,而组织内部的用户2w人,那么按照组织内外的区分毫无意义。
另外,如果有多个库表的情况,多个数据源进行加载数据处理的时候,最好是进行并行加载,这样就会提升加载时间。 -
表历史数据归档、清理
有些时候,一些数据在业务上是有生命周期闭环的,当这条数据的生命周期结束后,可以尽快的将其归档,这样减少业务批处理时的数据库压力。
3
部署态
批处理模块,比较影响体系结构,应该尽可能的与自己处理的数据源靠近。
如果多个系统模块,都需要批处理。尽量的每个模块建立自己的批处理模块,而不是建立一个大一统的批处理模块,这样对于业务领域聚合,以及数据库的管理等都会有非常多的问题。
单独应用模块与OLTP分开,处理自己的数据
批处理模块,应该独立部署,与联机交易模块分开。
另外,
实例,灾备模式等,机房
一般情况下,2个机房需要4个实例部署,进行灾备以及高可用切换。
4
监控管理态
运行监控
例如作业执行的统计内容,成功次数、失败次数,被终止次数、执行中次数。
以及一些任务的执行告警等功能。
最好有控制台,当然也可以自己根据JMX进行开发。
作业互斥配置,静态资源或者任务元数据的动态修改,配置更新热生效。
异常处理与故障转移、断点续做
当然,如果做成云平台,可能控制台的权限控制体系。
还有一系列的数据分析,例如依赖链状态查询,执行趋势分析。
参考:
-
https://www.cnblogs.com/jietang/p/5353220.html
-
https://www.cnblogs.com/javastack/p/15105397.html
-
https://blog.csdn.net/csucsgoat/article/details/116724221
-
https://mybatis.org/spring/batch.html
-
https://www.cnblogs.com/javastack/p/15105397.html
原文始发于微信公众号(架构突围):应用系统批处理模块的架构设计要点
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/170084.html