ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

金融核心系统云化改造:从Batch PaaS到多租户批处理平台的落地实践

金融核心系统云化改造:从Batch PaaS到多租户批处理平台的落地实践 简介一份聚焦金融行业核心业务系统云化升级的演示文稿面向保险/金融IT架构师、云平台规划者及运维团队。内容以传统金融公司技术陈旧JDK 1.4.2、批处理性能差、扩展困难等真实痛点为切入系统说明新一代核心系统的建设目标与云平台分层设计涵盖公有云、私有云、混合云多部署模式及IaaS、PaaS、SaaS服务模式。PaaS层包括流程管理、规则管理、内容管理、用户管理、批处理平台等模块并重点展示批处理平台基于ZooKeeper实现分布式并行计算、动态节点管理和故障自动转移的改造实例也涉及多租户数据、性能与安全隔离设计。资源包共1个pptx文件大小2.58MB约含项目简介、云平台架构、实现实例、总结四类内容已有91人学习浏览。通过这份讲解读者能快速理解云架构在核心系统转型中的技术选型、改造方式与资源复用思路对后续规划本企业系统上云有直接参考价值。1. 上云不是换台虚拟机把金融核心系统改造成云架构值不值这份资源讲的是一家中小型寿险公司农行控股怎么从 JDK 1.4.2、JSPServlet 的老系统走到支撑未来十年业务的云架构。公司业务每年增长 50%目标 1000 亿保费、2 万用户、1000 万客户老系统却频繁宕机、批处理慢、新软件集不进来。典型传统金融机构的困境资源有限、保守安全、遗留系统一大堆。方案没有选择推倒重来而是在私有云为主的基础上把 IaaS、PaaS 一层层落地其中批处理平台被改造成支持多租户的 Batch PaaS这个实例尤其有参考价值。适合正在做系统云化选型的架构师和开发负责人也适合想知道批处理、多租户到底怎么落地的从业者。2. 云平台选型与整体设计既有资产不丢PaaS 为核心2.1 部署模式与服务模式为什么私有云是主战场先说部署模式。方案里明确写了三种公有云、私有云、混合云排在中间的是私有云混合云写入远期规划。单独看这三个词不新鲜但结合这家公司的情况这个排序是经过考量的。传统金融公司不是不想用公有云而是业务数据合规、核心账务不能放在第三方机房这在保险行业尤其严格。私有云意味着把 VMware 这类虚拟化或容器底座装到自己机房业务数据不出门公有云放在外围系统或者弹性明显的场景混合云则是最理想但复杂度最高的远期目标。服务模式上方案把 SaaS 放在上层、PaaS 放中间、IaaS 在下层但真正花篇幅讲的是 PaaS。原因不难理解IaaS 只是把物理机或虚拟机做成池子解决了资源“能分”的问题没有解决“应用上线快不快”的问题。对开发团队来说更痛的是权限、批处理、报表、规则这些通用能力被反复建设。所以这个项目把 PaaS 作为核心列出了 10 个 PaaS 组件、3 个 IaaS 组件SaaS 待规划。从投入角度说IaaS 是基础购置成本PaaS 才是提升生产力和上线速度的关键SaaS 在金融保险领域还不成熟先不做。提示云架构选型时不要先谈技术先把部署边界、服务边界定了。私有云为主、公有云为辅、混合云远期这是传统金融比较稳的路径。2.2 PaaS 十大组件哪些买、哪些自建、哪些外包资源里给了一张很实在的清单。PaaS 层由这 10 个组件组成流程管理 IBM BPM、规则管理 IBM ODM、内容管理 ECM、监控平台 MONITA、分布式事务管理 DTX、用户管理 UM、批处理平台 Batch、报表平台 Report、渠道接入平台 CIPS、产品工厂 PF。实施模式上分三类商业产品购买、自主设计自建、外包开发。我按自己的理解重新归类一下组件类别状态选型逻辑IBM BPM商业产品购买完成流程编排成熟避免自研工作流引擎IBM ODM商业产品购买完成规则引擎标准能力强保险规则变化多ECM/MONITA/DTX/UM/Report/CIPS自建实施中业务耦合深需要贴身定制Batch 批处理自建完成要深度接入虚拟化和 ZooKeeper外购难满足PF 产品工厂自建完成保险产品工厂必须按自身产品线建模买与自建的边界就在这成熟通用、团队没精力长期维护的东西优先买业务规则、内部数据、要跟虚拟化深度打交道的场景优先自建。IBM BPM 和 ODM 放到现在看可能有点贵但当年选它们确实能降低交付风险。还有一个实施模式是外包开发方案里提到用了但没说是哪一块。以我的经验外包适合页面和报表这类外围功能核心批处理和多租户逻辑外包很难做明白。2.3 一条反常识的约束利用遗留系统、已购资产和现有人员知识这套设计里最不“技术流”的反而是它的约束。方案三次强调“充分利用遗留应用系统”“充分利用已购买软硬件资产”“充分利用现有人员的知识技能”。听起来像凑数其实这三条决定了整个项目形态。先说“充分利用遗留应用系统”。老系统是 JDK 1.4.2JSPServlet很多新软件集成不进来。但业务规则、账务计算、批处理逻辑这些代码里有大量验证过的算法和公式推倒重写的风险远远大于保留。常见的做法是把遗留系统拆成服务外层用新框架适配内部业务逻辑尽量保留而不是非要在新项目里复刻一遍。再说“已购软硬件资产”VMware、Oracle 12C、Weblogic 12C这些是已经花过钱的东西新核心系统继续用不搞无意义的换新。最后“现有人员能力”团队熟悉的是老 Java、JSP、存储过程让他们一步跨到微服务加容器项目大概率会烂尾。方案设计了五个基本概念的学习曲线就指向这个现实。为什么要强调这三条因为大量云化改造项目死在“推倒重来”上。自以为老系统一无是处三个月后发现光迁移数据就干了半年预算超了几倍。这个项目把“不能用新技术”也当成一种机会不追求技术最前沿只追求几年后还能维护。再往下方案提到保险行业最易变的五个要素渠道、产品、规则、流程、销管基本法。云平台要做的是把这五类变化尽量用配置或平台手段承接让 80% 的应用开发建立在基础模块之上。我看到实现路径是 6 个公共基础模块用户权限、批处理、报表、内容、日志监控、事务管理。把这 6 块做成 PaaS应用层就不用重复造轮子了上线速度自然会快。3. 实例拆解批处理平台从分布式计算到 Batch PaaS 的改造路径3.1 原批处理平台的三个硬伤这个比传统 IT 系统的痛处更典型。原平台处理分红批处理、满期批处理这种大批量数据任务是全散弹式的用户的批处理会自动分配到所有服务器执行结果大家都在抢资源数据库访问由批处理程序自行设定程序里写死连接串想连哪个库连哪个库所有用户都能查看和管理所有的批处理实例一点隔离都没有。三件事分别对应性能隔离缺失、数据隔离缺失、安全隔离缺失。改造后的 Batch PaaS 目标很明确用户只能查看和管理自己的批处理解决安全隔离用户的批处理自动分配到自己的服务器执行解决性能隔离用户只能访问自己的数据库解决数据隔离支持虚拟机动态分配、数据库动态分配、中间件动态分配其中后两项在建设范围内的完成度不同这一点后面细说。3.2 分布式并行计算模型Job、Task、Executor、SharedResourceHolder分布式批处理首先要有一套任务模型。资源里把一次并行计算任务叫 JobJob 会被拆分成多份并行执行的 Task每一份 Task 对应的执行逻辑叫 Executor。既要控制并发又要避免一处出错全盘重来所以还有一个 SharedResourceHolder 负责共享资源比如数据库连接池、缓存连接池、Spring 上下文这类所有 Task 都要用的东西。整个批处理平台由 Distributor 负责调度拆分Executor 做执行。员工学这套模型只需要掌握五个基本概念实际开发时实现其中 3 个子类即可继承 Job 实现拆分逻辑、实现 Executor 接口执行 Task、扩展 SharedResourceHolder 的公共资源初始化逻辑。我按自己的工程习惯理解了一下大概是这样的伪代码// 1. 定义一个分红批处理 Job public class DividendBatchJob extends AbstractJob { Override protected ListTask split(TaskContext ctx) { // 按主键区间拆成 128 份每份一个 Task ListTask tasks new ArrayList(); Range range ctx.getDataRange(); long step range.getSize() / 128 1; for (long i range.getStart(); i range.getEnd(); i step) { tasks.add(new DividendTask(i, Math.min(i step - 1, range.getEnd()))); } return tasks; } }这个示例里split 是 Job 需要实现的核心方法它不负责具体计算只决定把任务切成多少片。数量怎么定我一般不会直接写 128 死值而是结合 Executor 所在节点数来定每个节点分 4 到 8 个 Task 比较均衡切太少并行度不够切太多调度开销和重复连接数据库反而拖慢整体。再看 Executor 和 SharedResourceHolder// 2. Executor真正执行 Task 的逻辑 public class DividendTaskExecutor implements TaskExecutor { Override public ExecuteResult execute(Task task, SharedResourceHolder resources) { DataSource ds resources.getDataSource(core_db); // 按 task 携带的区间范围执行对应的数据更新 SQL return ExecuteResult.success(); } } // 3. SharedResourceHolder封装公共资源初始化 public class CoreSharedResourceHolder implements SharedResourceHolder { Override public void initialize() { initDataSourcePool(); // 初始化主库连接池 initRedisCachePool(); // 初始化缓存连接池 initSpringContext(); // 初始化 Spring 容器 } }这一段是大多数开发真正要写的东西。SharedResourceHolder 要保证在某个节点上只被初始化一次多租户环境还要根据租户选择不同的数据源。常见做法是节点启动时从 ZooKeeper 拉取租户与数据源的映射关系再按映射初始化连接池。初始化失败执行器直接退出不让任务在坏环境下反复重试。3.3 无单点故障、动态节点增减与自动故障转移资源里提到批处理平台具备三个运行期能力无单点故障、支持节点动态增减、自动故障转移。这三个能力是分布式批处理和传统定时任务最大的区别。无单点故障要求调度器不能挂常见做法是多节点部署 Distributor用 ZooKeeper 做选主。动态增减节点要求新节点能自动注册进集群旧节点可以随时下线不用改配置批处理自动在存活节点上重新分配。自动故障转移则要能在任务执行到一半时由调度器重新把未完成的 Task 指派给其他 Executor。这三件事落在 ZooKeeper 上就是典型的临时节点和 Watcher 机制。我贴一个常见的注册脚本#!/bin/bash # 新节点启动后向 ZooKeeper 注册临时 znode IP$(hostname -I | awk {print $1}) ZKzk1:2181,zk2:2181,zk3:2181 # 节点路径带上租户标签方便按租户调度 NODE_PATH/batchpaas/nodes/${TENANT_ID}_${IP} # 创建临时节点线程存活时节点存在进程退出后节点自动消失 /opt/zookeeper/bin/zkCli.sh -server $ZK create -e $NODE_PATH $IP临时节点的含义是进程活着节点就在进程一断节点自动消失调度器马上知道有 Executor 下线。新建节点后要再触发一次任务重分配把新 Executor 纳入调度范围。注意这里我用的是 zkCli.sh 做演示生产上应该用 Curator 之类的客户端封装。3.4 为什么是 Java Only平台约束也是一种保护方案在批处理平台后面标注了“Java Only”这既是约束也是策略。选型时如果团队技术栈是 Java那就全部走 Java道理很简单二次开发基于合作厂商产品厂商的 Executor 接口、SharedResourceHolder 都要给 Java 版本团队本身也只熟悉 Java。如果要让批处理节点同时支持 Python 脚本意味着节点要维护两套运行时调度器要维护两种 Executor运维排查问题时要叠加两种定位方式复杂度直接翻倍。Java Only 不是为了排他是把维护成本锁在可控范围内。4. 多租户与动态分配Batch PaaS 真正做成云的关键细节4.1 多租户不是加字段数据、性能、安全三层隔离这个项目用了一整页讲多租户而且反复强调“不只是加一个区分租户的字段”它要解决的是三个隔离问题隔离类型原系统问题改造后方案数据隔离用户能访问别人的数据库每个租户绑定自己的数据源程序无权随意连接性能隔离批处理任务互相抢服务器任务只调度到租户名下的节点池安全隔离用户能看到别人的批处理实例所有查询和管理接口强制按当前租户过滤数据隔离最简单也最容易做歪。很多团队实现方式是在业务表加一个 tenant_id 字段查询时 where tenant_id当前用户这样一套库一套表确实能骗过多数人但数据库层面根本没隔离一个租户的烂 SQL 可能拖垮整个库。这个平台的方案更彻底用户只能访问自己的数据库也就是说批处理运行时能用的数据源与该租户绑定的库强相关。用户申请了哪个库Executor 初始化时就用哪个数据源。这样隔离从连接池开始就分开了数据库层面的互相影响也随之消失。性能隔离的核心是调度策略。常见做法是给每个租户分配独立的计算节点组任务调度时不走全局随便分而是先找该租户名下的节点再在这些节点上做并行拆分。这样某租户发起的重任务再重也只影响自己名下的节点分配出去的节点数量可以做成配额避免一个租户占掉整个集群的多数资源。安全隔离有更隐蔽的坑批处理平台改造前登录系统管理页面的用户能看到所有节点的 Job 列表甚至能操作其他部门的批处理。改多租户时如果只改了数据库字段界面上最容易漏掉的就是“我的批处理”和“所有批处理”的权限边界。所以资源里明确把“用户能够查看和管理自己的批处理”当作新系统能力写了出来不做成全局列表。4.2 动态分配流程申请、审批、VMware 接口到授权回收动态分配是批处理平台做得最像 PaaS 的部分。从设计看它的运行流程是这样的用户租户发起计算节点申请虚拟化管理员审批系统自动调用 VMware 接口按需创建虚拟机批处理管理员授权给该用户使用用户的 Job 即可使用这些计算节点跑批处理这个流程看起来简单但每一步都涉及一个角色和一个后台动作。没有配额管理就会有租户无限申请节点审批和授权分开是为了避免“能创建虚拟机的人”和“能调度到该节点的人”是同一拨人产生越权风险。我一般会在这个流程里加一个关键动作授权的同时把节点注册进 ZooKeeper并标注租户属性否则虚拟机能创建出来但批处理调度器根本不知道它存在。补充一段模拟的接口调用逻辑# 创建虚拟机并注册到批处理平台 def create_compute_node(tenant_id, cpu, mem): vm_id vmware.create_vm(vm_templatebatch-executor-template, cpucpu, memmem, tenanttenant_id) # 虚机启动后执行初始化脚本 vmware.wait_for_guest_ip(vm_id) exec_id zk.register_node(/batchpaas/nodes/ tenant_id _ vm_id) # 给租户增加节点配额才能被调度 um_service.grant_node(tenant_id, exec_id, expire_days30) return vm_id这里有几个点要留意。vm_template 是预设好的 Executor 镜像里面预装了 JDK 和 Executor 应用新创建的节点起来后只要向 ZooKeeper 注册再用租户的共享资源初始化逻辑启动连接池即可。grant_node 相当于把刚刚生成的节点和某个租户做绑定关系即使物理上这个节点属于公共资源池请求进来了也只能被该租户调度。expire_days 这种过期机制很关键否则那些申请完不再用的资源永远收不回来。这个代码是我基于常见做法写的原资源没有给出具体接口名但它能说明整条链路的落点。凡是没想清 VMware、ZooKeeper、用户管理三者衔接的项目动态分配大多卡在“虚拟机创建好了但租户用不了”这一环。4.3 未完成模块的诚实清单数据库和中间件动态分配为什么难资源里有一个细节我觉得比整篇吹捧都有价值——它明确标记出动态分配里哪几块没做完。原文写的是虚拟机动态分配完成数据库动态分配未完成中间件动态分配未完成。这不是失败反而是这套方案可信度高的地方。我也确实在不少项目里见过类似的收尾方式。数据库动态分配难在哪难点不在“创建一个数据库实例”而在租户绑定。连接池要能在运行时动态创建、销毁和切换数据迁移怎么办新旧库切换的窗口怎么处理运维时如何保证每个租户的连接池参数一致。中间件动态分配同理Weblogic 集群、JVM 内存、Classloader 这些都是动态创建后要初始化状态的比虚机难度又上一个台阶。更重要的是业务风险。批处理跑出结果已经上线了数据库动态分配意味着账务数据可能在新库旧库之间漂移这直接触碰审计红线。稳妥的方案是把计算节点动态分配先落地数据库和中间件维持相对静态的拓扑等虚拟机资源池稳定运行半年后再逐步推库层动态化。这个决策顺序其实是相当聪明的。5. 踩坑与排查批处理 PaaS 改造中值得记住的五个坑5.1 多租户加一个 tenant_id 字段现象改造后的系统上线第一周A 部门看到 B 部门的批处理实例甚至能强行停止对方一个跑了一半的任务。 原因表结构确实加了 tenant_id但查询列表的 SQL 只对主表做了过滤关联子表、缓存、以及管理端的全局列表全部露出了所有租户数据。本质是把多租户当成了查询过滤器而不是数据访问边界。 解决所有的数据库访问强制走数据访问层由框架统一注入租户条件不允许 SQL 手写租户判断管理端列表的所有查询改为先过“我能看哪些租户”的权限判断再做数据查询。从那以后凡是要改数据层代码都要做一次租户穿透测试。5.2 动态创建的节点租户却迟迟用不上现象虚拟机管理员的审批通过了VMware 也创建了好几个 Executor 节点但用户跑批处理时调度器始终找不到这些新节点任务还是排队。 原因新节点启动后没有注册到 ZooKeeper 调度器或者注册了但节点路径上没带租户标识调度器无法判断该节点该分给谁。 解决把“创建 VM→启动初始化→注册节点→绑定租户→授权”拆成一个完整流水线而不是让虚机管理员手动点创建再手动配。建议写成一个自动化脚本在 VM 创建完成后立刻执行注册和授权步骤ZooKeeper 节点路径用租户 ID 作为前缀。5.3 ZooKeeper 集群脑裂导致同一个 Task 被执行两次现象某个节点网络闪断故障转移把 Task 丢给另一个 Executor 执行但最后发现原节点又恢复了两个节点同时处理同一个 Task分红批处理重复计算了两次。 原因故障转移机制处理不严旧节点没有强制停止新节点已经开始执行系统中也没有幂等控制。网络抖动触发的脑裂让两个节点都以为自己是任务的新归属者。 解决执行前在 ZooKeeper 创建一个带租户和 JobID 的临时顺序节点多个 Executor 竞争创建只有一个能拿到锁执行结果写入前再查一次全局的 job_execution_log 唯一键做幂等校验重复提交的任务直接丢弃。5.4 预设“管理节点不是瓶颈”任务暴增时被打脸现象平台运行稳定时管理节点 CPU 长期在 5% 以下于是团队认定管理节点不用扩容。业务高峰期任务数翻到几千个管理节点 CPU 干到 90%Job 提交超时ZooKeeper 频繁报连接数超限。 原因管理节点平时确实清闲但它连接的是 ZooKeeper 和数据库又承担调度决策任务量上来后频繁的会话心跳和 Job 元数据读写会把资源吃满。单机部署更是加重了这个局面。 解决管理节点按 2 主 2 备部署把 Job 元数据从数据库挪到 Redis 分片按租户做调度器分区某一租户的任务爆炸不会影响整个集群的调度对提交的任务做批量拉取而不是逐条走 ZooKeeper。5.5 计算节点扩了数据库被压垮现象给租户动态加了 20 个虚机批处理确实跑得更快了但过了两天数据库连接池满了主库的锁等待飙高其他在线业务也跟着变慢。 原因计算节点扩容了数据库还在原地。一个批处理节点默认初始化 20 个连接20 个节点就多出 400 个连接数据库连接池上限没跟着调任务并发抬上去后数据库锁竞争加剧又没有做资源上限管治。 解决动态扩容永远把数据库连接池配额一起算别只做计算节点扩容给每个 Executor 限制最大连接数单租户的总连接数也要做上限防止一个租户把数据库拉垮。资源里说数据库动态分配未完成其实真正的原因就在这——补上了计算节点能力数据库管理能力没跟上你还是没得到真正的弹性。6. 验证与进阶怎么证明这套 PaaS 真的撑得住6.1 四个维度的验收框架改造完成后我一般会从四个维度去验证不只看技术指标还要看业务团队是不是真的愿意用。维度验证方法核心指标上线速度拿一个新险种需求走完整链路从需求到上线的时间对比稳定性连续跑 7 天批处理观察故障转移Job 失败率、任务重试时长隔离性两个租户同时发起大量批处理互相影响延迟、资源争抢情况资源效率动态节点申请到回收的完整周期平均审批时长、节余资源比例上线速度是最直观的。老系统加一个新险种规则、批处理、报表、权限全要开发新平台上产品工厂和规则引擎已经把大部分逻辑配置化批处理只需要改 Executor 里的业务段上线周期能压掉一多半。稳定性靠故障演练我习惯每周主动杀掉一个 Executor 节点观察调度器能不能在几分钟内把 Task 重新派出去而不是等真故障来了再学。隔离性验证最容易被忽略。真正要测的是两个租户同时提交大规模任务时一方任务积压会不会让对方的核心分红批处理也跟着变慢。资源效率要关注授权回收如果申请了一堆节点跑完就晾着那动态分配就成了变相浪费。可以从 ZooKeeper 节点列表里查出 30 天以上没有任务调度的节点强制回收把资源退回公共池。6.2 后续演进从人工审批走向配额自助再走向全链路自动化这套云架构就目前的状态还留下两个明显的改进空间。一个是资源申请还是走审批流程高峰期会变成瓶颈。远期可以把人工审批改成配额制每租户有额定配比不超过配额直接自取超出配额走审批。另一个是全链路自动化把虚机创建、节点注册、授权、数据源绑定、任务发布串成一条流水线开发提交代码后自动完成部署和注册这已经是云原生要解决的事但脱离这批基础的地基谈云原生都是空话。从那以后我每次做完云平台改造都会把“已完成/未完成”的清单挂在项目墙上不遮掩半途而废的模块。未完成不是失败可能只是决策顺序的一部分。希望这份拆解能帮到你也祝你的批处理平台改造少踩几个坑。本文还有配套的精品资源点击获取
返回列表