场景
电商网站,商品和商家的促销活动时,会经常给商品设定一个标签,例如包邮、爆款、秒杀等。由于商品的数量繁多,不可能让运营人员人工对每个商品挨个设定标签(即打标),其一决定一个促销活动往往很快,时间上不许这么做,其二工作量巨大,人力成本很高,因此自动化的打标系统就诞生了,系统只需要添加一个标签,并选定要打标的商品范围,后台即可异步自动打标。
系统大致逻辑
后台采用定时器方式,于每天12点后开始运行,异步处理打标数据。
问题
随着商品的促销活动越来越多,参与的商品也越来越多。自从2017开始,自动预警系统开始每隔一个星期就报出服务器网卡流量超过100M的警告,对于一个对外提供服务的服务器来说,一个定时器独占100M的流量是多么严重的问题,这会直接导致其他的功能变的缓慢,或者某些IO造成堵塞。刚开始我们还没引起重视,一方面也是因为其他项目非常繁忙,要排查出这个问题不是一天两天的事情。事实总是在告诉我们,当一个小窟窿任由它放纵,事态就会朝着越来越严重的方向发展,结果可想而知发展成为每天早上10点就开始报100M流量报警,然后就是各个业务人员发来的一堆紧急处理问题的邮件,简直不堪其扰,苦不堪言。于是我们也到了不得不处理这个问题的时候了。
问题分析排查过程
既然是网卡流量超高问题,那自然得从网络流量的出入分析着手了。而且一个系统依赖调用了各个其他的独立系统,并不知道流量是别人的问题导致还是我们内部程序的问题导致。因此先定了一个大致的查找方向:
1、让服务器管理员监控入流量来自哪一IP。
2、让服务器管理员监控出流量往哪个IP。
3、对应IP服务器部署了什么应用,提供的是什么服务。
当服务器管理员将监控的结果告知我时,我恍然大悟,便最终确定了原因及优化方案。服务员告知我入流量来自一台对外提供接口的服务,而这个接口服务也是我们团队在维护的。接口服务提供的是基于RMI的服务,这个服务所做的事情非常简单,就是查询数据库或者缓存中的数据,然后返回。
于是我就猜想,如果入流量非常高,只有可能是查询的数据量非常大,要么是查询了大字段的数据,要么就是查询了字段非常多的大表数据。然后根据猜想,我找到了定时器中所有被调用的接口。根据接口挨个去接口服务应用中找到对应的SQL,最终定位到一个非常另我震惊的SQL上:这个SQL居然查询了表中全部200多个字段,而一个条记录200个字段,数据量就能达到0.5M。定时器大量的在for循环中调用接口获取数据,流量当然报警了。
到此,原因算是弄明白了,但问题仍未解决。原因在于,为什么一个简单的业务需要查询表中全部的字段,硬生生的消耗系统资源,而不考虑对其他功能的影响。带着疑问,我走查了定时器的逻辑,发现一个令我非常愤怒的结果:查询了表中的全部字段,但却只用到了其中的5-6个字段,其他200多个字段都是打酱油的,瞬间想找到设计这个程序的人拜访他的家人。
恍然大悟之后,剩下来的事情就简单的多了,方案就简单的多了:新增一个接口,只查询真正需要的几个字段即可。至于编码的工作,就交给小徒弟去完成吧。
总结
在编写SQL的过程中,很多人习惯使用select *,或者把很多无用的字段加入到结果集中。特别不建议这么去做,以上经历就是血淋淋的教训。
网友评论