更多课程 选择中心

软件测试培训
达内IT学院

400-111-8989

记一次测试环境、正式环境发布遇到的问题及总结


背景

新功能发布到测试环境,验证 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: '#: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: '#: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: '#: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 即可,却不需要改动原有的代码。

总结

发布文件不要依赖于环境的修改,可以依赖于环境选择不同的配置,发布后要全面地验证功能,不能掉以轻心。

预约申请免费试听课

填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:软件测试中的配置管理是做什么的?
下一篇:解读日常工作中开发和测试的关系
  • 扫码领取资料

    回复关键字:视频资料

    免费领取 达内课程视频学习资料

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

陕西省

湖南省

贵州省

云南省

广西省

海南省