背景

最近开发微信公众号,部分功能上线后,为了保证不影响线上正常使用,新功能的开发测试遇到以及需要解决的问题如下:

  1. 调用微信公众号高级接口(授权,支付等)需要配置域名访问,本地测试繁琐,且不能覆盖线上已部署的链接,对已有服务造成影响

  2. 公众号前端业务逻辑涉及到缓存cookie,需要保证测试与生产环境的cookie不冲突

  3. 给需求方演示测试demo,最好要保证与即将上线的子菜单等交互一致,提高交流效率

  4. 测试数据(包括数据库,redis缓存,日志等)与线上数据进行分离

  5. 测试环境与线上部署分离,保证互不影响,提高线上的高可用

  6. 测试环境与生产环境实现自动化部署,提高开发测试效率

解决方案

申请测试公众号以及测试域名

为了满足给需求方演示测试demo,保证与即将上线的交互体验一致,想到最简单的方案就是重新申请公众号供测试使用(幸好以学校研究院的名义,,要不个人申请就没戏了,,,);并且为了保证前端cookie在两个公众号下不冲突,所以测试的时候使用了与生产环境不一样的二级域名,进行cookie隔离

后端的配置分离

目前由于只有一台云服务器,对于后台工程的配置分离,包括:测试与生产工程的端口号,数据库,redis库,微信开发者ID与秘钥,日志。

项目使用了springboot,配置文件目录如下截图:

将工程分为本地(dev),测试(online-test),生产(online)三种环境,并配合application.properties基础配置文件使用,将与环境相关的变量写入相应的properties中即可进行分离,如下列举application-online-test.properties中的配置内容:

注:数据库的分离即是新建不同的库进行区分访问,redis即通过库号区分访问,日志则通过日志名称来区分

后端的部署分离

后端部署脚本执行的流程为:

  1. 使用maven生成jar(本项目为springboot内嵌tomcat,直接执行生成的jar即可提供后台服务)

  2. 在云服务器上执行kill脚本,杀掉并删除待替换的jar进程

  3. 将新jar包传到云服务器上,执行相应jar的启动脚本(启动脚本包括执行jar在后台运行,指明相应的application-??.properties的文件)

因为只有一台云服务器,需要区分测试与生产环境的jar,使用的方案是两种环境生成不同名字的jar,这样也便于kill脚本与启动脚本通过名称来区分jar,进行部署的分离执行,相互不影响

使用maven来生成不同的jar名称,需要修改pom.xml

<profiles>
     <profile>
         <id>online-test</id>
         <properties>
             <project.name>"测试环境的jar名称"</project.name>
         </properties>
     </profile>
     <profile>
         <id>online</id>
         <properties>
             <project.name>"生产环境的jar名称"</project.name>
         </properties>
     </profile>
 </profiles>
 
 <build>
     <finalName>${project.name}</finalName> // project.name即为profile中的properties的标签名
.....其他配置信息
 </build>

最后执行命令 mvn clean package -Ponline-test -Dmaven.test.skip=true,-P后面为profile的id名称,即可生成不同名称的jar

最后执行云服务器的启动脚本,即可启动新的jar服务

nohup java -jar  'jar包的文件位置' --spring.profiles.active='配置文件的后缀(online或online-test)'> /dev/null 2>&1 &
前端的配置分离

前端的配置变量包括:请求测试与生产端口号不同,域名不同(涉及授权等重定向链接的不同),微信公众号的ID不同。

代码上将这些变量写到全局一处调用,通过开关注释进行分离控制

前端的部署分离

因为使用单台云服务器,测试与生产环境的前端工程都需要使用到80端口,因为微信高级接口有些仅允许80端口程序调用,所以对于ngnix的配置,使用了配置虚机主机的方案。

具体步骤如下:

  1. 确保容器/etc/nginx/nginx.conf文件中有:include /etc/nginx/conf.d/*.conf;

  2. 在容器目录/etc/nginx/conf.d/下面新建文件site1.conf,site2.conf,文件名任意,后缀名需要与步骤1配置的一致,这里为.conf。site1代表我们的生产环境工程,site2代表我们的测试环境工程,该文件编写如下:

server {
    listen 80;
    server_name //代表该虚拟主机的二级域名
    root //前端工程代码在服务器中的位置;
    index index.html index.htm;
    ...其他配置略
}

前端工程的部署脚本流程是将代码替换到相应配置的目录下,平滑重载ngnix即可

systemctl reload nginx.service  //reload重载文件,客户端无异常
方案总结

通过申请新的测试公众号,部署不同的域名配置到子菜单上,可以达到与线上公众号相同的交互,前端通过访问后端不同接口的服务,将数据库,redis缓存,日志信息通过后台配置实现了生产与测试的完全分离,可以说如上的解决方案,满足了开始列举的所有需求点,最终将前后端的部署实现脚本自动化,也节省了部署时间,提高开发测试的效率。

待解决问题

测试与生产环境分离后,对于测试通过的功能需要上线,则需要运行线上的部署脚本,这时前端和后端代码的部署仍然会导致线上的服务暂时不可用,但目前只有一台服务器,实现灰度发布等策略来去提高服务的高可用显得有点儿困难,,,,,,所以,有机会与条件再去学习下吧,,,,,,