记一次测试环境、正式环境发布遇到的问题及总结
作者:观力 发布时间:[ 2017/5/3 11:05:46 ] 推荐标签:测试环境 配置
背景
新功能发布到测试环境,验证 ok,发布到正式环境,因为正式环境上还没有数据,用了假数据验证,也 ok(只能说前端的功能 ok)。第二天,产品接到客户,需要用这个新上线的功能,我有点忐忑,因为用户量比较大,涉及到的 money 也比较多。客户的数据添加后,果然出事了 ORZ,正式环境访问不到数据,于是周日回到工位,打开我的代码编辑器...
问题
我发现这个错是因为我注释了一行代码引起的,我为什么要注释这行代码呢?原因如下:
有个服务叫 L5,它是做负载均衡用的,主要特征如下:
1、名字服务:以SID(由模块ID和命令字ID组成)为关键字,通过SID取得真正的IP和端口地址,使得IP和端口配置对调用者透明,运维变更配置更方便;
2、负载均衡:以请求成功率和请求延时这两个关键指标进行动态权重计算,动态均衡各个被调服务器的负载,达到较好的整体服务质量;
3、故障容错:迅速自动屏蔽错误率高或有故障的机器,并进行适时探测,待故障恢复后自动恢复;
4、过载保护:实现对单台机器或者整个模块机器的过载保护能力,防止雪崩现象。
参考
比较抽象,简单说一下我的理解:
前端请求 node 端,node 端请求提供数据的服务端,提供数据的服务端有很多个,它们都装着相同的数据,是怕哪个机子负载过重,或者 down 掉了。node 端怎么才能知道哪个机器负载、错误率比较低呢?这个要靠 l5 了,假如现在有三台提供数据的机器:10.xxx.xxx.16、10.xxx.xxx.17、10.xxx.xxx.18,公司这个 l5 系统可以为这三台机器申请 l5 的配置 id(实际上要比这个复杂一点,这里屏蔽了具体的业务逻辑),比如现在申请的 id 是 00001,那么 node 去请求数据的时候是这样的:
request({
type: 'get',
url: 'http://10.xxx.xxx.xxx:8080/getData'
l5config: 00001,
}).done(function(){
// ..
})
因为有了这个 l5config,那么 10.xxx.xxx.xxx:8080 这个 ip 不重要了,任意的 ip、域名、端口都可以,实际上会根据 l5 的配置去找 16、17、18 这三台,具体请求哪一台,l5 的系统会去找负载低、错误率低的机器。
这是我简单理解的 l5
问题详情:
前端去请求 node 端,node 端会被部署在开发环境、测试环境、正式环境上,正式环境通过 l5 去请求了 16、17、18 这三台机获取数据,但是 16、17、18 这三台机的数据都是正式的,平时测试同学一般操作不了这里的数据,所以出现了 10.xxx.xxx.55 这台机器,用来提供测试环境的数据。我当时是这么干的:
// 测试环境
request({
type: 'get',
url: 'http://10.xxx.xxx.xxx:55/getData'
//l5config: 00001,
}).done(function(){
// ..
})
测试环境里我注释了 l5 的配置,因为 55 这台机器没有申请一个 l5 的配置 id,我直接通过 url 的方式去请求了,想着等到代码要发布到正式环境时,我把注释取消掉,结果发布时忘了取消注释,那么等到这份代码被发布到正式环境,不是去请求 16、17、18 这三台提供正式数据的机器了,而是请求了 55 这台提供测试数据的机器,结果客户的数据找不到了。
解决办法
当时临时取消了注释,因为是周日,与 leader 沟通后,走了免测发布流程,暂时解决了问题。但是这样并不完美,leader 说发布文件不要依赖于文件的修改,要从机制上杜绝,要依赖于环境变量。这里我们要说说 NODE_ENV 这个环境变量。
NODE_ENV
这个变量的起源于 express,express 生成的 app.js 中通常都会有这么一段语句:
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
这里的 app.get('env') 是访问了 process.env.NODE_ENV,这个 NODE_ENV 并不是一个特殊的变量,默认为 undefined,据说是 express 盛行之后,这个变量便盛行了,process.env 中还可以访问其它的环境变量,比如 JAVA_HOME、CLASSPATH、Path 等等。在 windows、linux 中,设置环境变量指的也是这个。
来看一下现在的需求:开发环境、测试环境、正式环境对应有三台机器,在这三台机器中,需要各自有个环境变量来标识哪台机器是哪个环境,然后根据环境变量引入不同的配置文件。因为目前的项目为 ALPHA,所以定义了一个叫 ALPHA_NODE_ENV 的环境变量,而没有使用 NODE_ENV 这个变量(担心这个变量太火被别的业务使用了,然后被我一改,其它业务瘫痪了)
设置 ALPHA_NODE_ENV
这里为开发机、测试机配置 ALPHA_NODE_ENV 环境变量为 development、testing,undefined 视为正式环境
linux 中的环境变量是这样设置的:
在根目录下,进入 etc 目录,修改 profile 文件,在里面增加一条语句:export ALPHA_NODE_EVN=development,测试环境的设置为 testing。修改完成后,在命令行中输入 source ./profile, 这样修改的环境变量生效了。点这里查看参考文档,注意如果是通过命令行来设置,而不改变文件的话,那么只在当前命令窗口生效,新开的命令窗口不生效。
修改环境变量的时候,因为用的是 vim,这里附上一篇使用文档
相应的文件配置
这里新增了三个文件:
1、developmentConfig.js
2、testingConfig.js
3、productConfig.js
三个文件配置不一样,比如:
// developmentConfig.js
this.l5 = {
'10.xxx.xxx.16': undefined
}
// testingConfig.js
this.l5 = {
'10.xxx.xxx.16': undefined
}
// productionConfig.js
this.l5 = {
'10.xxx.xxx.16': 00001
}
有一个总的 config.js:
// 区分环境配置
var alphaNodeEnv = process.env.ALPHA_NODE_ENV;
this.alphaConfig = require("./"+ (alphaNodeEnv? alphaNodeEnv : "production") + "Config.js");
调用的时候:
var config = require('./config.js');
request({
type: 'get',
url: 'http://10.xxx.xxx.xxx:8080/getData'
l5config: config.alphaConfig.l5['10.xxx.xxx.16'], // 这样在开发环境和测试环境里是 undefined,在正式环境会通过 l5 请求数据。
}).done(function(){
// ..
})
这样写的好处有:
1、可能不同的接口对应的 l5 配置不一样,那么这里的 config.alphaConfig.l5['10.xxx.xxx.16'] 中的 10.xxx.xxx.16 相当于一个对应特定 l5 的 key,如果不同的 l5 可以在文件中增加配置了,比如多了一个请求天气的接口,也需要通过 l5,那么:
// productionConfig.js
this.l5 = {
'10.xxx.xxx.16': 00001,
'10.xxx.xxx.66': 00002, // 其实这里的 key 是什么都无所谓了,只要能被调用到行
}
2、新增一个环境,比如预发布环境,那么只需要在预发布环境设置环境变量 ALPHA_NODE_ENV 为 preDeployment,增加 preDeployment.js 即可,却不需要改动原有的代码。
总结
发布文件不要依赖于环境的修改,可以依赖于环境选择不同的配置,发布后要全面地验证功能,不能掉以轻心。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11