之前线上一直是Node v0.12.1v0.8.6
版本,觉得太低,因为目前都已经v0.12.1
了,这么大的一个跨度,再不升级可能就真的跟不上时代了。
于是找了伟大的OP
同学协助将各线上线下环境都升级一遍,当然,升级的步骤还是线下升级,观测一段时间没问题了再更新的线上。
结果,线下更新后完全没发现问题,更新到线上后,时不时Fatal
,想想也是醉了;毕竟有些API已经deprecated了!
举俩栗子
1、Response write after end
线上用的静态文件是自己用Node写的,其中有一段儿代码是这个样子的:
function _endResponse(data, file, headers, req, res) {
if (data == null) {
// 文件没找到
base.staticLog(404, req, 'File not found');
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('File [' + file + '] is not found!');
res.end();
} else {
// 文件没找到
...
}
}
因为所有静态文件合并都是在静态文件服务器内自动完成的,类似: http://biz.meilishuo.net/~shop:common/light/bootstrap+shop:common/light/iconfont+shop:common/light/theme+shop:common/uploader+shop:common/introjs+shop:common/api/api.css?v=330a5670d3 就是在静态文件服务器自动将页面上所有需要的css文件合并到一起,一次性加载。
所以上面的_endResponse方法会执行多次,假设其中的某一个文件不存在,那么问题就来了:res.end()
已经执行,下一个子文件的请求又来了,就会出现response write after end
的情况,意思就是说:在新版本的Node中,不允许在一个HttpResponse已经end之后再有write操作,因为整个connection已经断掉了!
简单的fix办法,就是加一个判断:
function _endResponse(data, file, headers, req, res) {
if (data == null) {
// 文件没找到
if(res.connection) { // 如果connection还没断,就可以继续写
base.staticLog(404, req, 'File not found');
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('File [' + file + '] is not found!');
res.end();
}
} else {
// 文件没找到
...
}
}
2、Get client ip from web server
工作中有个FeDev
工具,其中一个本地开发的功能就是需要获取本机在公网的IP,一个简单的办法就是访问webserver的一个接口,从接口获取Client Ip
,在Node v0.8.6下,是下面这样获取的,完全没问题,得到的地址是:192.168.148.93
function getIp(req) {
var ip = req.clientIp ||
req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
return ip;
}
但是web server升级node到v0.12.0
以后,得到的却是:::ff:192.168.148.93
这样的IP,直接导致功能不能用,简直坑,简单的Fix办法:
function getIp(req) {
var ip = req.clientIp ||
req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
// 简单加工一下:我也不想这么弄。。。
return ip.split(':').slice(-1).join('');
}
其实还遇到好多问题,暂时只列举这俩,也提醒大家,任何软件升级,都得排查清楚兼容性,之前其他团队计划把PHP版本从5.3.x升级到5.5.x,结果也是,线下没问题,上线以后直接崩溃,无奈,到现在都还没升级成!