背景
收到客户投诉说是我们的系统登录过程很慢,几乎要以分钟来计算。奇葩的问题。客户环境也是复杂,查看部署环境需要各种权限、堡垒机、指纹秘钥等等。需要客户各种权限的人员输入各自的秘钥才能看一眼数据库,看一眼代码, 看一眼部署环境,看一眼运行日志。发现真正解决的问题得时间不到一小时,整个过程要一天,呵呵。
倒腾了一个上午搞清楚了项目的运行环境,以及问题情况。问题表象是通过check、right、system账号登录系统的确是非常的慢。登录过程中涉及到单点登录(单点登录也是奇葩的单点登录,貌似是通过跨域设置cookie来完成的登录状态持久化的)。
问题分析
其实整个过程慢的原因和单点登录没有关系,因为系统的确是已经跳转到应用系统的首页了,但是首页的响应时间的确是非常长。客户端浏览器接收到数据后渲染很快,重新刷新页面,有需要等待很长时间客户端才接受到数据。说明问题已经很清楚了,后端代码有问题。
定位到这里基本上就可以去审核代码了,不过根据客户的描述信息来看。只有三员用户登录才会很慢,所以感觉很奇怪,这和用户有什么关系。抱着疑问通过各种协调找到代码后。简单分析页面的所有请求(这里其实是通过源码简单猜测的请求,因为客户现场不允许使用谷歌,只有IE8,TMD万恶的IE8,我诅咒它一辈子包括微软,因为微软的IE,真的不知道国内好多单位生产力降低了多少档次)。
言归正传,项目使用的底层技术是ssm、jsp。查看jsp没有什么特别的代码。也没有其他的request请求,大概花了一小时,找到对应的后端request 映射方法。仔细检查了代码后(这里说明下项目代码的确是非常乱)。
发现问题,真实奇葩的代码,看代码分析业务,简单描述业务场景,需要统计系统日志(用户登录,用户所有操作日志,修改数据,新增数据等事务操作)总量,根据总量(比如日志超过100W数据量后)来提醒管理员需要清理归档日志。
其实业务非常清晰简单,但是代码明显经过两手,第一版本的代码是selectAll获取集合,通过集合获取seize大小判断日志量是否超过控制。同志们,有没有被惊吓到,多么简单的业务,多么奇葩的代码实现,这就是不重视代码质量,不重视技术含量的结果。所有人(没有例外)做项目的是只管实现,项目负责人只管搞需求,不管代码质量,不管实现思路,没有代码审核。真的是很奇葩啊。
然后可能某个技术人员发现了问题,这段代码被注释了,关键是只注释了size比较的代码,改成了sql语句count的方式,但是selectAll获取集合的代码没有被注释,我居然在生产环境上看到这样的代码,这简直是对程序员的一种侮辱。首先第一版代码到第二版代码,这都经历了什么,别和我说是不小心没有注释全,一共就不超过10行代码,另外集合对象后续的业务逻辑完全就没有被使用,IDE有明显提示变量是无用的变量。
然后这段代码只有在check、right、system账号下才会被执行,估计也是业务需要吧,只有这三个用户才有权限去归档备份日志数据。
根据以上信息基本上就可以确定问题原因了,就是selectALL惹的祸。从第一版本代码,可能被其他人发现了代码问题,然后有人修改了,可是修改的人也是半斤八俩,可能只知道通过获取集合size来判断数据量不合适,其实真正的问题是selectAll,想想为什么业务系统需要分页,selectAll的可怕之处足以让系统宕机。数据库首先要获取所有数据然后传输返回给应用系统,mybatis需要通过反射将result解析成java 对象,如果数据量一大,后果可想而知。
好吧,最后不吐槽了,不求技术人员被重视,不求技术人员有明确岗位制度,不求技术人员有明确的上升空间。只求老板们尊重下技术人员,在和技术人员聊天时别把需求调研、人员管理、资源协调、沟通交流的那一套理论来衡量一个技术人员,因为完全没有可比性。另外个人认为做技术的不是做不了人员管理、需求调研、资源协调、沟通交流。就我自身而言,如果我放下对技术的热爱,全身心投入到管理,需求调研上,我相信我比很多人都做得好。
总结
-
本次问题其实不难,主要是客户运维环境复杂混乱。
-
在分析问题是没有谷歌浏览器,只有IE8,内网USB接口全封闭。所以在分析问题需求精准定位,不然可能会被误导。
-
推荐一款线上Java诊断工具arthas,类似这种问题arthas一个命令就能精准定位class中的方法执行时间,定位问题。当然本次问题因为运维环境不允许外来软件进入内网系统,所以没有用到任何工具,全凭认为经验分析。
-
其实以上问题通过代码质量管理平台sonarqube能很容易的扫描到无用变量以及无用代码等质量问题。