写点什么

银行祖传系统重构实例:创立12年,只支持Python 2,跑着500多个应用程序

2020 年 8 月 20 日

银行祖传系统重构实例:创立12年,只支持Python 2,跑着500多个应用程序

提到遗留系统,你会想到什么?


  • 还在使用Java 5的路过

  • JDK 1.6的我不说啥了

  • 很多坑

  • 难维护

  • 从零开始(重写)

  • 盼着IE什么时候不再能使用


遗留系统


对于遗留系统,程序员们并不陌生。据维基百科介绍,遗留系统是一种旧的方法、旧的技术、旧的计算机系统或应用程序。


张逸认为,遗留系统首先是一个还在运行和使用,但已步入软件生命周期衰老期的软件系统。它符合所谓的“奶牛规则”:奶牛逐渐衰老,最终无奶可挤,然而与此同时,饲养成本却在上升。这意味着遗留系统会逐渐随着时间的推移,维护成本会不断地增加。


在《从300万行到50万行代码,遗留系统的微服务改造》一文中,技术琐话阐述了遗留系统的一些共同特征。


  • 庞大的单体应用:遗留系统大多是多年积累下来的“巨无霸”系统,以单体应用形式呈现。

  • 难于修改:多年的代码累积过程中疏于重构,导致代码的可读性和可扩展性较差。

  • 维护成本很高:在庞大的代码中寻找 bug 的根本原因可能会比较困难。此外,运维也是难题,比如在本章开头提到的 Perl 系统,没有 APM 工具支持它的监控。

  • 学习成本高昂:由于设计陈旧或技术过时,可能了解遗留系统技术和业务的人已经很难找到。

  • 缺乏质量保障:由于过去缺少投入,许多功能基本上没有自动化测试来保障质量。


事实上,在传统企业甚至互联网企业往往存在大量的遗留系统。这些遗留系统大多都能正常工作,有的可能还运行着关键业务或者持有核心数据。但是,大部分遗留系统通常经常存在技术陈旧、代码复杂、难以修改等特点。


我们看到,有的遗留系统给企业带来不可挽回的损失:


系统出现故障,当年负责编写这个程序的开发者却在15年前去世,现在已经无人能看懂他的代码,结果一个bug导致千万损失。——《程序开发者去世,代码没人懂,一个bug导致千万损失》。


还有的遗留系统在企业技术变革中慢慢淡出:


笔者曾经维护过一个Perl实现的网站,在2015年被解耦前,它已经工作了十几年,为公司占领市场立下了汗马功劳。奈何技术陈旧,维护困难,最后在微服务化过程中慢慢淡出。——《从300万行到50万行代码,遗留系统的微服务改造


当然,也有遗留系统至今活得很好,默默贡献自己的力量。


印象深刻的遗留系统


我在一家银行工作时,遇到了一套令人印象深刻的遗留系统。


它最初创建于 2008 年(北京奥运会那一年),花费数周时间进行开发。整套系统具有完整的 CI、CD、单元测试、代码审查、自动部署等功能。自创建以来,大部分时间,它的核心基本保持不变,但是外围有许多改进(代码审查、日志记录、性能、身份验证等)。


从某种方面说,它相当于是公司内部的 AWS lambda 等效系统。


你可以编写一个 Python 脚本(Python 是该系统唯一支持的语言),大约 5 分钟内就能审核完毕并投入生产,准备供世界使用。


这个系统并不是官方层面的“战略”解决方案,它不为人知,也没有做过广告宣传。但是,它被频繁用于多个业务部门,并且不时有新的发展。因为它太好用了,所以大家都没法抛弃它。


我们部门有个暑期实习生,他利用这个系统,只花了 3-4 周就基本完成了他们的小项目(实习期应该有 2-3 个月)。而同时,其他实习生群体还没有弄清楚如何在“战略”框架内交付应用程序。


我最后一次统计时,那里运行着 500 多个应用程序。值得注意的是,生产日志显示,其中 80%处于活跃状态。



外科手术式维护


不过,在不断变化的软件世界中,所有美好的事物都必须迎来终结。到头来, 这套系统还是要重新设计或被抛弃,原因如下:


  • Python 2.7即将寿终正寝

  • 身份验证库已经弃用

  • 中间件有很长时间没有重新编译或升级了

  • 有一些潜在的UI改进需要完成


为了拥抱变化,这个系统开始升级。而在升级到第一批生产脚本时,我们就遇到问题。


有两个用户每隔 1 小时就报告一次问题,我们研究问题后发现其仅限于 IE 浏览器。在 IE 浏览器中,某些功能无法正常运行。


实际上,这家银行很早前就弃用了 IE,转而支持 Chrome 浏览器。全公司 25 万的员工被要求禁止使用 IE 浏览器。如果尝试在 IE 中打开某些站点会报错,会提示你改用 Chrome。这对用户导航有副作用,因为所有内容都是相互连接的(想象一下 report.example.com 链接到 otherreport.example.com 并调用 internalapi.example.com,可是某些 URL 是被阻止的)。


好消息是,最近的升级并没有倒退回去,而是简单解决了这个问题。IE 被屏蔽,并向 5000 位开发人员发出了通知:不再支持 IE 浏览器。问题解决了。


供参考:最好硬屏蔽IE以改善用户体验,IE用户习惯了在其他浏览器中重试。也许最近几年开发的内部应用中有三分之一无法在Chrome之外运行,不是页面空白,要么就是到处都有损坏的小部件。


于是,升级按计划进行。在最后,我们遇到一个小麻烦:一个独立的脚本停止工作了 。


该脚本最初创建于十多年前,也就是这个框架刚创建后的几个月内。这是最早发布的应用程序之一,也许从历史上来看是第 8 个(现在有 500 多个)。


它实际上不是代码,而是某种模板。众所皆知, 该框架带有自己的模板语言和例程 (二十一世纪的开发人员应注意:请使用 jinja 进行模板化)。已经没有东西还在用这个模板功能了。团队进行了一些调整,然后系统又恢复了正常工作。


最终,升级完成。


新版同时支持 Python 2.7 和 Python 3.7,支持 OpenID Connect 和 Kerberos,在各处添加了一些消息和错误以简化使用,还更新了开发文档等等……


经过 12 年的可靠和忠诚的服务,这款旧系统并没有被弃用。恰恰相反。它还在兢兢业业做事,并且肯定还会再活起码 12 年,比现在所有的 JavaScript 和战略框架寿命都更长。


唯一的缺点是 lambda 请求的启动时间较长(基线为 5 秒)。它适合处理偶尔访问的报告和 API,不适合用于高性能 API 或缓存,后面的情况下最好使用其他技术,推荐 tornado 用作 Web 服务器 Web 框架。


看遗留系统的“正确姿势”


在《关于遗留系统,看看Google怎么办》一文中,Cheng 哥总结了几点,个人觉得挺好,分享给读者。


1. 保守态度,不轻易改变


老的系统,面对的场景没有发生太大变化,原来什么模式就是什么模式,不要为了改变而改变,比如运营商的 CT 系统、银行的核心交易系统等关乎国计民生。


同时,因业务特性的原因,本身不会有很频繁、很大的变更,这种时候,现有手段,慢一点、稳妥一点,哪怕流程繁琐一点都没问题。如果改,就可能会带来极大的风险,也不会带来太大收益,不改,也能维护下去,孰优孰劣,自然就清楚了。


现在,运维有一种提法,叫做双态运维,就是针对系统特点,分为稳态和敏态,不同场景采用不同的模式。


2. 重构过渡


如果业务场景变化了,要求系统必须能跟上节奏,这种情况下,建议通过重构,且逐步迁移的方式过渡。也就是,根据新的场景,设计适应的技术架构,能够满足效率、稳定和成本的要求,然后老系统上的业务和流量逐步迁移过去。


如果是直接在承载业务运行的老系统上改,成本和风险会非常高,实际情况下是不可行的。


3. 从现在开始,重视标准统一


前面提到传统行业的软件体系,大多是多厂商建设,标准不统一。但不管是做 DevOps,还是 SRE,甚至最基础的自动化,标准都是前提中的前提。所以,如果当前正在规划新的技术体系,或者有针对某些遗留系统重构的机会,从一开始规划好各种标准体系,就非常重要,建设前没有标准,事后再去统一标准,基本就没有机会了。


互联网的技术体系,从最早期的单体架构,没有标准,到系统拆分的服务化演进,形成统一标准,再到基于统一标准的运维自动化、持续交付以及稳定性建设,最终形成大中台的体系,也是遵从着这样一个过程和规律走下来。


只不过,互联网公司在早期没有太大的业务和技术的包袱,所以可以小步(甚至大步)快跑,大胆试错,快速迭代,整个过程的进展会更快一些,但是规律是一样的。不过,当规模到了一定体量,所面对的问题,跟传统行业也是一样的,一样会有遗留系统。既不可能随意放弃(还在承载业务),也不可能说重构就重构,成本和代价是必须要考虑的。


对遗留系统,你有什么看法?欢迎留言告诉我们。


参考资料:


https://thehftguy.com/2020/07/09/the-most-remarkable-legacy-system-i-have-seen/


2020 年 8 月 20 日 15:021856
用户头像

发布了 497 篇内容, 共 177.0 次阅读, 收获喜欢 1022 次。

关注

评论

发布
暂无评论
发现更多内容

来啦!2020 Java开源项目权威排名解读:Spring Boot排名稳定、Shiro未上榜

Guide哥

springboot 开源项目 springsecurity shiro

Go语言分布式系统配置管理实践--go archaius

华为云开发者社区

go 分布式

Selenium高效拍档-HtmlUnit

dothetrick

Java 自动化测试 测试开发

前端异常监控 Sentry 的私有化部署和使用

智联大前端

前端 监控 异常 sentry 错误

深入讲解拉链表,还怕面试官问?

大数据老哥

大数据 数据模型 数仓项目

智慧社区平台开发解决方案,小区一体化综合服务平台建设

WX13823153201

图灵测试已过时,AI 需要新基准测试;别了Flash,Adobe播放器正式停运

京东智联云开发者

云计算 AI 量子计算机

依赖倒置原则与单一接口隔离原则

andy

在线教育的发展

anyRTC开发者

AI 音视频 WebRTC 在线教育

Spark 3.0 关键新特性回顾

hanke

spark 开源 大数据技术

中国用户规模最大教育科技独角兽作业帮再获投资机构青睐

Geek_459987

第五周 技术选型(一) 学习总结

feiyun123

mybatis使用及SQL语句优化小结

华为云开发者社区

数据库 mybatis 索引 实用SQl语句

从 RxJS 到 Flink:如何处理数据流?

Apache Flink

flink 流计算

招聘 | 腾讯云大数据,期待您的加入!

小小的一朵云

大数据

统一软件开发框架对企业信息化的影响

力软.net/java开发平台

软件开发 框架开发 信息化

GitHub 的野心,5600 万开发者的新社区

打工人 Coco

GitHub 开源项目 开源社区

区块链加密货币钱包系统APP开发|区块链加密货币钱包软件开发

开發I852946OIIO

系统开发

京东面试:说说MySQL的架构体系

田维常

MySQL

数仓实时化改造:Hudi on Flink 在顺丰的实践应用

Apache Flink

flink 流计算

大作业一

走走,停停……

创业公司用 Serverless,到底香不香?

Serverless Devs

Java Serverless 运维 云原生 前端

纵观 Excel 演化史,开发者如何通过“表格技术”提升企业生产力

Geek_Willie

Excel SpreadJS

重学JS | 深入理解Object,必会知识点汇总

梁龙先森

前端 编程语言 前端开发 前端进阶

从源码层面理解ArrayList 扩容策略

geekymv

Java 扩容 ArrayList

七大关于DevOps的误解,你中了几招?

陈琦

DevOps 运维 开发 自动化测试

为PostgreSQL的表自动添加分区

PostgreSQLChina

数据库 postgresql 开源

原始时代对分布式架构的探索

carol

揭开KPI异常检测顶级AI模型面纱

华为云开发者社区

华为 AI 数据 决策树

大作业二--知识点整理

Nick~毓

看透Spring MVC源代码分析与实践

田维常

Java

银行祖传系统重构实例:创立12年,只支持Python 2,跑着500多个应用程序-InfoQ