Nodejs升级到v0.12后 进入全屏
line

之前线上一直是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,结果也是,线下没问题,上线以后直接崩溃,无奈,到现在都还没升级成!

阿里巴巴-钉钉-开放平台,能力开放&开发者运营岗位招聘中, 期待你的加入!
钉钉开放,让应用开发更简单
充分开放,是钉钉的重要方向!除致力于为开发者打造丰富的开放API, 更易接入的场景化能力包, 完备的应用开发工具之外, 还需要持续构建开放能力的布道、开发者生态运营体系,包括培训、沙龙、大会、社区合作等等。业务在快速发展,我们也还需要更多优秀的小伙伴加入!

评论区域

line