当前位置: 首页 > 后端技术 > Java

服务端框架重构之旅

时间:2023-04-01 14:33:06 Java

由于公司业务依然采用泡顶玫瑰+翡翠+树脂的技术架构,导致新员工学习成本高,且框架本身多年无人维护,所以被决定迁移到springboot2+mybatis+tomcat。前言下面是我的迁移实践。任何开发一般都分为三个步骤:写代码、测试、监控。许多程序员不注意测试和监控。这就是俗称的“杀埋”。写完代码,也就算是结束了。默认程序已准备好使用。问题取决于接口调用者的反馈或上线后的排查。一方面会影响你的个人声誉,别人会认为你不可靠;另一方面,很容易给公司造成严重的损失。对于框架迁移和重构工作,测试和监控尤为重要,因为所有接口都可能出现问题。准备工作1)调查springboot框架和paoding-rose框架的不同语法,尽可能找出代码中paoding-rose的特殊规则,并进行列表比较。比如paoding-rose的json数据需要加上“@”符号,@Get、@Post等特殊标签,以及ControllerInterceptorAdapter等Intercepters等。paoding-rose基于spring,底层实现为一样,但是为了方便使用做了自己的封装和适配,并且非常重视一些项目中的一些特殊用法。2)考察mybatis和jade框架的异同点。之前公司的jadeframework是通过zookeeper获取配置的。jade提供了主从分离、分表查询等功能,mybatis原生不支持;jade是基于注解sql的,mybatis需要改成xml配置形式。3)与部署相关的异同。从resin到spring内置的tomcat,是否可以更换相关的部署配置,如何适配公司的部署体系。阶段性迁移参考其他项目的迁移经验,决定分两阶段迁移,便于定位问题和确认影响。第一阶段:迁移dao层,jade到mybatis第二阶段:Paodingrose+resin迁移到springboot2+内置tomcat主要是controller层和相关配置文件。这个阶段迁移dao层遇到的问题主要是sql文件重写和主从分离。1)SQL文件重写SQL文件重写主要是体力劳动。如何将70多张表的SQL改写无误,真的很难。初步计划是使用通用的mapper框架,这样可以生成一些通用的方法。但是后来深入了解后,发现业务SQL比较复杂,基本的默认SQL都不能用,必须重新生成模型文件才能使用通用的mapper。这种情况下,原来的model文件都需要改,controller和service中的业务逻辑也要改。修订。在使用generalmapper修改了几张表后,发现费时费力,而且代码改动太大,风险太大。因此,我放弃了使用通用的mapper,改为手写mybatis相关文件。之前自动生成了一堆mapper文件,模型字段名和数据库表字段名的映射map还是可以用的,方便多了。我通过重写和自我测试做到了这一点。我在test目录下写了一个对比测试,对比新旧框架在相同请求参数下的异常返回值(select语句)。重复劳动容易粗心/疲劳,容易出错,对比测试帮我发现了很多问题。2)mybatis实现了主从分离。这里我们采用AbstractRoutingDataSource+mybatis插件的形式。通过mybatis插件拦截Executor的查询方法和更新方法。对于所有的select语句,从库的DataSource都是以ThreadLocal变量的形式指定的。.整体迁移框架整体迁移框架主要分为几个部分:Controller层的迁移,主要是注解和返回值。对于注解,同事写了一个python脚本,自动重写两个框架对应的注解,大大提高了工作效率。泡定玫瑰的一些特殊用途。例如返回值@符号,代码中其他一些地方使用了旧框架。返回值@前缀让我深深感受到代码干净的重要性。因为项目代码很老,经手过很多人,到处都是@符号,代码搜索不好匹配。在paodingrose框架中,通过识别json结构返回@符号,返回数据会去掉,而springboot不会。这种问题没有错误日志。一旦上线,客户端就无法解析返回的结果。问题很严重。严肃的。先改一下旧框架可以找到的地方,然后去掉maven依赖。如果找不到包,自然会报错,一个一个改。启动相关配置由于在线同一台机器上部署了多个节点服务,所以服务端口和日志配置文件必须是可配置的。我这里的实现是log4j2.xml文件和fatjar放在同一个目录下。在项目的resource目录下放置一个application.yml文件,在fatjar的同级目录下配置一个application.properties,包含以下三个值:server.port=<%=scope["config::http_port"]%>server.tomcat.accesslog.directory=<%=scope["config::prog_logdir"]%>logging.config=<%=scope["config::basedir"]%>/log4j2.xml读取配置文件时,application.properties中的配置优先级较高,从而保证服务启动端口、访问日志目录等日志目录都是可配置的。代码改写后,就是繁重的测试工作。首先,它是一个对比测试。对于所有重要的接口,都进行了新老框架下接口的对比测试,黑盒对比,直接requesthttp请求对比返回值,请求参数尽量真实数据抓包。有些接口有特殊的行为逻辑,或者里面有一些动态参数,每个请求都不一样,需要灵活处理。一共对比了大概80个接口(日请求前80的接口)。然后部署到测试机上,用客户端抓包看返回值有没有异常,同时观察服务端的错误日志。(顺便说一句:将错误级别的日志放在一个单独的文件中,这样查看错误日志会很方便)。因为是一个很老的项目,客户端经历了很多版本迭代,最新版本的客户端可能不再使用这些代码,所以肯定是不完整的。测试环境测试没有出现新的问题,这样的话,就可以开始上线了。迁移dao层时,分为两个阶段。第一阶段启动几张表,确认mybatis的配置没有问题,然后替换所有表。有60多个节点在线。先上线一个节点,观察错误日志。几个小时后,没有抛出SQL相关的异常,再去其他机器上线。上线后一定要及时观察各种告警和错误日志。这里顺便介绍一些在线监控和日志记录的做法。本行主要分为两部分:机器和nginx运维同学建立了机器指标监控板和阈值告警,以及基于nginxloghttp请求的pivot统计。比较重要的机器指标包括:cpuloadmemoryremainingamount/homepartitiondiskremaining和partitiondiskremainingnetworkinboundtrafficoutboundtraffic比较重要的域名服务指标包括:域名下http接口请求4xx和5xx的数量和比例以及服务器业务占比业务由服务器端的同学处理,主要分为两部分:第一部分是基于监控的指标监控和告警。第二部分是接入公司的elk和druid数据。将业务日志,如接口请求日志、服务异常日志等放入elk中,方便您定位查询问题。另外服务器端的同学还做了一个基于elk日志的Exception报警机制。当某类Exception超过正常值时,会触发短信和邮件告警。完善的监控告警系统是重构的可靠保障。本次重构无重大线上问题。但上线后,通过监控告警发现了很多小问题,并及时纠正。总的来说,重构进行得很顺利。一方面得益于前期的充分准备和其他模块的一些经验,另一方面得益于对比测试和在线监控报警系统。在重构一个3000万DAU、17亿请求/天、32k峰值qps的服务时,一定要小心谨慎。为确保没有问题,必须进行对比测试和在线报警。我的对比测试主要是dao层和接口层面的离线和在线对比测试。最好能在线跑一段时间,和真实流量对比一下(成本比较高,需要运维同学的支持)。本文由博客多发平台OpenWrite发布!