一个单体架构程序员的技术成长之路

2010年毕业后,加入了一家传统行业的公司做Java开发。转眼八年过去了,产品架构在近一两年也开始由单体架构转变为微服务架构。重点还是想回顾下单体架构下开发的一些心路历程。

刚加入公司,幸福的入职培训过后开始加入了项目。那时还没有开始敏捷开发,一个人负责一个模块。公司有严格的KPI考核,个人业绩与个人所负责模块的质量直接挂钩。所以一名新人加入公司,通常会分配到谁都不想接的模块。当然,这是我后来才知道的。

当时有位三年经验的老员工即将内部调动到别的城市工作,他负责的模块交到了我的手上。计算机专业科班出身,并且在校时熟读《Java编程思想》两遍,内心觉得不是啥事。等看到代码后,直接傻眼了。代码行数倒不是很多,不到5000行的样子。其中一个for循环占了大概3000行!你没看错,是一个for循环。本身对项目的业务知识不熟悉,代码里又各种特殊处理,只能一点点啃了。每天用eclipse debug,两周后,逐渐理清了这个循环的基本逻辑。如果是现在,我肯定会先做一些不改变代码逻辑的重构,拆分小方法,抽取重复逻辑等等,当时是不具备这个意识和能力的。很快,这个模块发布到外场商用了。这样的代码在商用环境的表现可想而知了,各种严重的故障单纷至沓来。前面说过,个人业绩和个人所负责模块的质量直接挂钩,可能读者会认为我的业绩很差。恰恰相反,我半年考核得了优秀!并且成为了部门的优秀毕业生!除了公司鼓励新员工的考虑以及领导对我工作态度的认可,负责的这个模块也贡献不少。虽然质量很差,但是问题严重啊,问题严重到领导经常被投诉,严重到领导经常来我工位前督促,这个故障什么时候能解决。虽然问题严重,但是我解决问题速度快啊。

如果没有维护过这种代码,你不会体会到《重构》《代码整洁之道》这些书中的观点的可贵。阿里去年推出的《阿里巴巴Java开发手册》,里边的很多条目我们都踩过坑。比如

【强制】ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException
异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是
ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。
【强制】在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均会产生 ConcurrentModificationException 异常。

还有,曾经维护过一段代码,这段代码使用了一个数据结构Map<String, Map<Sting, Map<String, Object>>>,业务逻辑主要围绕这个数据结构展开。笔者为了搞懂这个数据结构,在公司熬到凌晨两点,无奈放弃!还有,对HashMap的理解,对面向对象的理解,都是在这个过程中不断加深的。

很多知识点你只是看过是无感的,只有犯过错、被坑过才会掌握!
去年阿里推出这个手册后,我一直在思考为什么我们或者其他公司没有推出这个手册?我想一方面是阿里的影响力,但是也能看出阿里对待技术的严谨以及对业界的责任感。这样的企业是值得尊敬的!

前面的那个模块在维护了一年多后跟随项目终止了,若干年后和那个项目的项目经理在一张桌上吃饭,他告诉我说:“那个模块的代码已经不能用烂字来形容了”。

后来开始开发一个消息驱动的业务模块,大概流程是这样的(我们的代码主要在红色框中):


阶段1.png

阶段1:流程是这样的,我就是这样做的。来一条消息,按这个流程一条道走到黑。
这种设计很快暴露了问题:
1.处理效率低
2.系统A不仅对接系统B一个系统,由于系统B的处理效率低下,经常导致和系统A对接的其他系统出现问题。
效率低怎么办,上多线程啊!
阶段2:系统A来一条消息,系统B启动一个线程处理
由于刚开始商用,消息量不是很大,效率问题暂时解决了,也不会阻塞系统A了。
大概半年后,业务量上来后,这种设计的弊端呈现了:线程启动过多,OOM了。
也就是从这个时候开始,逐渐开始系统学习Java的多线程知识。

阶段3:系统B用线程池处理
这种设计不会OOM了,但是效率问题没有根本解决。这个时候开始了各种性能优化的探索:
1.优化各种JVM参数
2.系统C查询数据库效率低,所以我们直接连接系统C的数据库,用各种SQL关联查询提高效率。
3.数据生效到系统A效率低,我们做消息收集批量处理。

这样优化后,系统性能还算差强人意,在外场商用了近三年。
在此期间,运维的同事反馈了不少问题:
1.有时候只能处理消息A的请求,消息B的请求处理不了
2.数据库查询经常超时,导致整个业务请求处理失败。
研发侧也暴露了一些问题:
数据模型一旦发生变更,查询数据库的SQL语句就必须重写,工作量很大。
为了解决上述问题,有了如下的设计:

阶段4:线程池分类,消息处理设置超时机制。

阶段4.png

主要优化点:
1.按照消息类型,每种消息设置一个独立的线程池处理,线程池的配置通过properties文件动态生效。
2.按照业务功能,查询数据库和数据生效设置专门的线程池。
3.每条消息处理设置超时机制,避免局部失败影响整体。
这两步优化完成后,市场的反馈已经非常好了,各种性能问题不复存在。
考虑到后续业务量进一步增加的可能性以及架构的稳定性,继续改进:
阶段5:引入数据库缓存和领域模型。

阶段5.png

主要优化点:
1.引入缓存机制,进一步提升数据查询效率
2.建立领域模型,业务处理与底层数据库模型解耦

至此,单体架构下的系统B设计告一段落。
近两年,产品开始向微服务架构转型。引入Spring Cloud系列技术,当笔者第一次看到Hystrix框架,看到舱壁模式、断路器模式等概念的时候,颇有点相见恨晚!原来我们折腾这么多年的设计,业界早已实现。接触到Rxjava对线程池的分类,也与我们按照业务功能对线程池分类异曲同工。我们自己实现的缓存机制,业界更是有很多优秀的实现。至于我们痛定思痛后抽取的领域模型,在《实践领域驱动设计》等书中早已阐述明白。贫血模型到充血模型的演进,服务层的提取,等等。

不得不承认,在传统行业八年的技术成长与互联网公司是没法比。互联网公司的技术之所以先进,我想主要是他们面临的外部压力更多,促使他们不得不去改变,不得不不断研究新的技术方案。但是,如果在互联网公司只是做一个小螺丝钉,一入职就是在成熟的技术框架内开发,也未必会对这些技术有多么深刻的理解。为什么要有领域模型?为什么要用缓存?为什么用Hystrix?甚至为什么面向对象设计要遵循SOLID五原则?这些问题笔者在八年的职业生涯不断挖坑,不断填坑的过程中领会到的自然要比直接从书本上看来要深刻的多。

现在几乎各个公司、各个项目都在上微服务架构,都在玩docker。跟随技术潮流本身值得鼓励,但是笔者始终认为,如果你的问题在单体架构下没有想明白,只是引入了各种容器技术,微服务技术,你的问题不会得到根本的解决。比如,我的阶段1设计完全可以放在一个微服务中实现,以容器的形态发布。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335