神州系统是中通自主研发的网点智能管理平台,为网点提供与下属网点、承包区、业务员、客户之间的收、派、代收增值等结算工具,通过系统自动算账和结算,网点整体结算效率提升至2倍以上,降低了财务运营成本。同时通过财务结算的自动化,网点收件和到件扫描操作效率约提升50%。
系统还通过大数据计算,将客户的运费、件量、发件区域占比、重量占比等数据报表快速准确地展示出来,方便网点分析客户,提升了网点的市场竞争力。另外,还提供了网点整个运营环节的数据监控,帮助网点纠正错误操作,减少异常率,提升了网点管理水平,降低了网点的管理成本。
为了保证系统的高可用,实现海量运单数据的实时账单运算、出账以及数据分析,我们的技术人员都付出了什么样的努力,神州系统的架构刚开始并不是流行的微服务架构,这中间又发生了什么?下面请大家跟着我一起,探索神州系统的发展历程。
神州系统自2017年1月立项,根据当时的情况分析,其中最重要的2个因素对我们决策有着直接影响。
第一个因素:数据量大,每日账单数据量1600-2000万不等;
由于MySQL数据库单表记录数过多会导致检索效率下降,数千万记录就会导致普通查询效率低下,对于聚合函数,更是连千万级数据都无法支撑,而我们的数据却有数亿。为了解决这种问题,我们使用dangdang公司开源框架sharding-jdbc分表分库的解决方案,以便于我们将单表数据量控制在千万左右。根据业务我们制定了3种分表规则:按网点、按单号、按时间。
网点的账单数据理论上不会出现交际,正是借助这一点,我们将账单的数据按网点分表,查询时针对一个网点查询,这样既能满足业务需要,又能满足系统性能需要。
而对于热点数据,在系统设计的过程中,需要多网点共享数据时,比如同一个单号被多个网点扫描操作,需要将部分数据共享在多个网点中,我们则可以采取单号分表,将多个网点的信息,记录在一个单号上。而按时间周期统计的数据或计算的中间结果,则采用按时间分表。
上面所说的分表规则都是标准化的规则,但是标准化的分表规则,也许并不能完全满足实际需要;比如我们就遇到了这样的问题,按网点分表时,几十个网点被分配到1张表中,其中一个网点业务量非常大,数据占整张表的97%,使用的时候,不单当前网点无法正常使用,其他网点也受到了牵连。此时使用特殊分表规则,将次网点的数据,单独存入一张独立的表,此表中只有本网点数据,根本不需要维护网点id的索引,可以把更多有效的索引资源放在其他业务字段上,大大提高了检索效率。
另外我们采用了TBSchedule实现分布式调度,使海量账单数据由多台机器分开运算。既保证了海量数据计算的时效,又保证了服务器不会重复运算相同的数据。同样我们可以使用自定义的分片规则,让多台服务器的工作量尽量地保持平衡。
第二个因素:研发时间少,项目要在3个月内上线。
由于时间的因素,为了能够快速实现产品需求,达到尽快上线运行的目的,采用单体式架构方式开发。由于单体式架构简单,易于调试,只需要简单运行此应用。易于部署,只需要把打包应用拷贝到服务器端,通过负载均衡,在后端运行多个副本,就可以轻松实现应用扩展。
前端页面采用 angularJS1.0,前后端分离模式开发(其实是java程序员在做前端开发)。既可以减少服务器渲染页面消耗的性能,又兼顾java程序员的前端技术水平,减少前端页面的开发难度。
项目上线之初,我们也面临层层考验,首先大量的js和html文件请求到tomcat,导致链接被耗尽,因此我们添加了自己的nginx服务器,将静态资源部署在nginx上,不但减少了tomcat服务压力,也让我们的前后端分离开发更接近于标准化,为我们后期做微服务架构改革打下基础。其次大量的导出数据严重消耗了我们的服务器资源,因此我们设计了基于前端的下载,在服务器端不生成文件,改由ajax请求数据,浏览器中组装生成文件并保存,成功解决了这个问题。
不幸的是,单体式架构有很大的局限性。应用会随着时间推移逐渐变大。由于业务的发展迅速,不到1年时间,我们那个小而简单的应用已经成长为了庞然大物。此时的代码复杂性高,整个项目包含的模块非常多,依赖关系不清晰。
开发时启动一次项目已经需要3分钟,这还不包含编译的时间,开发电脑配置不好的话,会经常导致卡顿甚至死机,并且所有模块代码集中在一起,各模块代码提交时需要解决各种冲突,耗费大量时间。
此时的开发团队很痛苦。开发和部署举步维艰。而最严重问题是这个应用太复杂,以至于没有人能单独搞定他。因此,修正bug和添加新功能变的非常困难,且耗时。由于不能快速的做出成绩,整个开发团队都会变的消极。
而且我们的性能也达到了一定的瓶颈,所有的功能都堆积在一台服务器上运行,导致服务器硬件已经不能很好的支撑如此多的业务代码和数据,硬件资源会产生很大的浪费,且性能很不稳定,有许多宕机隐患。于是我们拆分了业务代码,调整了部署方式,利用nginx反向代理,将不同的业务请求指向不同的服务器,处理不同的业务。
如图所示,我们的每一个模块都是可独立运行的项目,互相之间没有依赖。采用了这种方法,我们以最小的成本,解决了性能上的燃眉之急(单体式架构向垂直架构的转变)。
但是这样的项目依然有一个很大的弊端,就是对于基础功能,被其他功能引用的同一段代码可能存在于多个项目中。代码重复率高,维护难度大。一旦这些功能需要修改,则需要同时修改多个项目的代码,并导致所有项目都要重新部署,成本非常高。
我们在业务功能相对稳定的时候,投入了大量精力,重新调整了我们的架构。采用微服务架构方式,将神州系统按业务域划分为多个服务。但是系统架构的改造,不是一蹴而就的事情,我们将改造分为了三步执行。
第一:制定新的系统框架
定义代码规范,代码工具等;
第二:停止向老的项目中添加功能,所有功能用新的框架开发及部署
当单体式应用庞大到无法管理时,应该停止让其继续变大,也就是说当开发新功能时不应该为旧单体应用添加新代码,最佳方法应该是将新功能开发成独立的微服务;
第三:旧功能服务化
对旧的功能,根据业务需求以及系统开发需要,排期修改。每当抽取一个模块变成微服务,单体应用就变简单一些;一旦转换足够多的模块,单体应用本身已经不成为问题了,要么消失了,要么简单到成为一个服务。
将单体应用分解为多个微服务,解决了单体应用过于复杂的问题。使开发和维护变得更容易。服务内部可以自由的设计解决方案,实现对外透明。即使重写单个微服务也不会太困难,相比重写整个单体应用容易多了。每个微服务独立部署,开发者不再需要协调其它服务部署对本服务的影响。这种改变可以加快部署速度,并且每个服务可以独立扩展。
微服务架构中的每个服务都可以由专门的团队来开发。开发团队之间解耦,服务内部独立迭代,有利于充分利用人力资源,减少了团队管理的难度。
以上内容都是实践经验,交流促进步,研讨共成长,感谢大家耐心地阅读,谢谢。
此文系作者个人观点,不代表罗戈网立场
-END-
农夫山泉23-25届校园招聘供应链类岗位
4949 阅读顺丰社招运营经理;B端销售;仓储管理经理;支付业务负责人;客户管理岗等
4418 阅读益海嘉里(金龙鱼)2025校招供应链、物流储备生
4429 阅读盒马社招运输经理;店仓管理专员;仓储业务物资管理高级专员;店仓经理
4173 阅读京东社招项目运营岗;客户体验分析;配送运营岗;客户经理岗;营业部负责人岗
4111 阅读华润啤酒2025届校园招聘物流管培生
3991 阅读特斯拉智能制造校招专项:24-25届物流、供应链类岗位
4009 阅读曼伦2025校招供应链物流岗位
3816 阅读新华三集团2025届校园招聘供应链类岗位
3655 阅读KK集团2025届全球校园招聘供应链岗位
3646 阅读