系统上线时的10大坑!!!
前言
最近缺项目经历想快速提升项目实战能力(包含多个AI项目),或者最近找工作,或者想学习AI的小伙伴,可以看看下面👇🏻的这个链接(或许真的能够帮到你)。
系统上线时,确实非常容易出问题。
今天跟大家一起聊聊系统上线前的10大坑,希望对你会有所帮助。
1.没初始化数据
没初始化数据,这个问题可能是上线前,最容易出现的问题之一了。
比如:你在表中新加了一个mapping_status字段,1:表示已映射,0:表示未映射,默认是未映射。已映射状态需要通过sql脚本初始化,否则通过mapping_status字段查到的都是未映射状态的数据。
但有时候初始化数据,还要考虑初始化数据的时机,特别是发布pre(预生产环境)时,如果急急忙忙就把某些数据初始化了,可能会影响线上功能。
比如:你在pre环境通过sql脚本,向某张表中insert了几条数据,但pre环境和prod(生产环境)用的是同一个数据库。
这样就会导致你在pre环境添加的数据,被prod(生产环境)的用户看到。如果他们用这样数据,做一些业务操作,可能会出现系统问题。
因为此时pre环境部署了最新的代码,但prod(生产环境)却还是用的老代码。
所以初始化数据,一定要写到上线的checklist清单中,把初始化数据的场景也要写清楚,哪些工作是要在pre环境做的,哪些工作是要在prod环境做的。
2.缺少某个类
我们有时候在系统上线时,会出现系统部署了,但是没法正常启动的情况。
从服务器的日志中可以看到,缺少了某个类,或者某个接口。
这时候要分两种情况:
- 缺少公司内部的某个类。
- 缺少第三方的某个类。
如果是缺少公司内部的某个类,很有可能是因为SDK或者contract没有deploy。
这时候就需要联系你依赖的SDK或者contract的提供方,让他们感觉在maven上发布相关jar包。
如果是缺少第三方的某个类,可能是因为生产环境没有上传相关的jar包导致的,一般情况下,开发、测试环境,跟生产环境的maven仓库是分开的。
这个问题在上线前,很容易被忽略。
3.代码发错分支了
当你看到这个标题时,可能有点不屑,生产环境不都是发master分支的代码吗?为什么还会发错分支呢?
比如:今天你有一个线上bug,需要紧急处理,拉了一个hotfix分支。你们组的另外一个同事,也有一个bug,也拉了另外一个hotfix分支。
然后你的已经在st环境上提测了,并且测试通过了,而你同事的还没有测试通过,还有些问题要明天才能改为。
但你的bug比较严重,需要今天就上线。
于是你在gitlab上提了一个merge request请求,合并代码到master分支,但是却提错了分支。
此时,你们老大合并了代码,然后发了生产环境,最后发现功能不对。
在提交代码时,我们一起要看清楚分支,千万不要提错分支。
4.系统参数没配
我们在代码中会经常加一些配置参数,方便今后可以动态调整它的值,而不需要重启服务,比如:
@Service
public class UserService {
@Value("${susan.test.userName}")
private String userName;
public String test() {
System.out.println(userName);
return userName;
}
}如果该UserService类被你的api服务和job服务同时使用了,而你在apollo或者nocos中,只给api服务增加susan.test.userName的配置。
这样你们在部署job服务时,由于缺少必要的配置参数,服务大概率会启动失败。
对于这种情况,我们在增加配置参数时,要确认一下该参数的使用范围,这个功能是被哪些服务在使用,一定要给相关服务都加上该配置。
如果你使用@Value注解,有个好习惯是给参数加上默认值:
@Service
public class UserService {
@Value("${susan.test.userName:susan}")
private String userName;
public String test() {
System.out.println(userName);
return userName;
}
}这里使用:susan就可以加默认值。
这样即使你的job服务没有配置susan.test.userName参数,在服务启动时至少不会报错。
5.忘了配菜单
有时候,我们开发的是后台管理系统的功能,有专门的UI页面。
一切准备就绪,数据库脚本执行了,代码也正常发版了,但测试同学去测试的时候发现有点懵,找不到新功能的入口。
这时候你恍然大悟,原来没配置菜单。
然后你找人把菜单配合了。
后面测试测时,又发现没有权限。
最近缺项目经历想快速提升项目实战能力(包含多个AI项目),或者最近找工作,或者想学习AI的小伙伴,可以看看下面👇🏻的这个链接(或许真的能够帮到你)。
由此,在我们系统上线的checklist中一定要将相关菜单和权限列清楚。
6.没法回滚
我们在上线系统时,通常有95%的情况是可以上线成功的,但也有5%的情况会上线失败。
如果今天要发一个大版本,需要迁移数据,表的结构都改变了,需要将历史数据从老表迁移到新表。
由于你的系统,还依赖于其他的多个系统,你们今天一起上线。
其中有一个系统上线后,发现的bug比较多,但今天处理不完。
没办法,为了不影响用户,今天只能将所有系统回滚。
但由于你的表都改变了,数据直接写入了新表,没有写入老表。这时候就比较尴尬,你的系统回滚不了。
所有我们在做系统设计时,一定要考虑回滚方案,万一上线失败,需要回滚。
对于新老系统升级的场景,我们可以使用数据双写的方式。用户新增或修改数据的请求,同时写入新表和老表,这样后面就能直接回滚代码了。
此外,在设计表结构时,如果新加了NOT NULL的字段,最好设置一个默认值。
不然的话,万一上线失败,回滚了代码,老代码没有给新加的字段赋值,此时保存数据,会直接报错。
正常情况下,生产环境的数据库表是不允许删除字段的,因此有个好习惯就是给新加的字段设置默认值。
7.消费被误消费了
假如我们有pre和prod两个环境,但为了减少维护成本,尽量保持pre的真实性,apollo配置用的同一套。
如果在pre环境mq的消费者,同时在prod环境也有一个mq的消费者。
但由于pre环境和prod环境用的同一个topic,如果某条mq消息,被pre环境消费了,可能会导致prod环境的数据出现异常,特别是pre环境有bug的时候。
或者某条pre环境产生的消息,被prod环境消费了,而prod环境还是运行的老代码。
因此,非常有必要将pre和prod环境mq的topic配置分开。
我们可以在系统启动时,给SpringBoot增加启动参数,例如:
java -jar -Dsusan.message.topic=test -Dserver.port=8081 -Dsusan.message.topic=topic_pre app.jar这样就能实现,不同的在环境参数定制化的需求。
8.只上线了部分节点
我之前遇到过某个新功能上线后,测试同时说该功能时好时坏。
我当时各种查原因,最后发现代码没有问题,是运维同学,在部署服务节点时,当时有5个节点,只部署了3个节点,有2个节点还是运行的老代码。
因此系统上线之后,我们要留个心眼检查一下,服务节点的启动时间,能够看到某些服务节点是不是真的部署了。
同时检查一下这些服务节点是否都是up的状态,有没有处于down状态节点。
9.job没配
有时候,我们开发了一个新的job功能,上线之后,发现job并没有执行。
最后发现错误有点低级,原来在xxl-job的管理后台忘了配置该job。
这个问题其实跟之前说过的菜单和权限一样,要在上线的checklist中,将job的相关配置列清楚,不然很容易遗漏。
10.依赖的服务没发
你这次新开发的功能,需要远程调用另外一个服务的api接口,而这个api接口是他们新加的。
你们双方约定了一个上线时间,结果你上线了,但他们没有按时上线。
这就悲剧了,你上线的功能由于没调到新的api接口,导致功能上线异常。
因此,如果你上线的系统,需要依赖于其他的系统,需要在checklist中写明依赖关系,以及系统的上线顺序。
一定要等你们依赖的系统全部上线之后,才能上线,不要急急忙忙上线,不然白上线了,可能会出现很多问题。
或者有个开关控制,如果依赖的系统没有上线,则可以暂时屏蔽新功能的入口。
此外,数据库脚本也非常容易出现问题,具体内容可以看看我的另一篇文章《系统上线时SQL脚本的9大坑》,里面有非常详细的介绍。
最后给大家总结一下上线前的checklist清单,需要包含哪些内容:
- 数据库脚本
- 初始化数据脚本
- 项目的git地址和分支名称
- 需要部署的服务名称
- apollo配置参数
- xxl-job相关配置
- 菜单和权限配置
- 服务的依赖关系和发布顺序
- 特殊一下上线要求,比如需要手动调用某个接口。
- 回滚方案
当然可能还有一些情况我没有考虑到的,欢迎各位小伙伴在留言区补充。
最近缺项目经历想快速提升项目实战能力(包含多个AI项目),或者最近找工作,或者想学习AI的小伙伴,可以看看下面👇🏻的这个链接(或许真的能够帮到你)。