satans17 / satans17.github.com Goto Github PK
View Code? Open in Web Editor NEWmy blog
my blog
npm 中的模块版本都需要遵循 semver 2.0 的语义化版本规则。
版本格式:主版號.次版號.修訂號,版號遞增規則如下: 主版號:當你做了不相容的 API 修改, 次版號:當你做了向下相容的功能性新增, 修訂號:當你做了向下相容的問題修正。 先行版號及版本編譯資訊可以加到「主版號.次版號.修訂號」的後面,作為延伸。
https://www.npmjs.org/doc/package.json.html#dependencies
https://www.npmjs.org/doc/misc/semver.html
http://deadhorse.me/nodejs/2014/04/27/semver-in-nodejs.html
在ES3中,使用关键字做标识符会导致“Identifier Expected ”错误,而使用保留字做标识符可能会也可能不会导致相同的错误,具体取决于特定的引擎。在ES5中,关键字和保留字虽然不能作为标识符 使用,但可以作为对象的属性名。在ES5中的关键字和保留字中,新增了let和yield。为了保证最大的兼容性,不管是ES3还是ES5中的关键字和保留字,都不要作为标识符使用。
ES5允许使用用户定义的属性描述来覆盖给定属性的enumerable、configurable、writable、get、set等属性了。具体方法是使用定义在Object对象上的静态函数。
最大的语法变化,就是引入了严格模式,可以通过语句"use strict"; 来开启严格模式,在代码顶部添加整个脚本启用严格模式,在函数内部添加则只对该函数启用严格模式。严格模式下主要的变化有:
http://raphaeljs.com/
Raphael 是一个用于在网页中绘制矢量图形的 Javascript 库。
目前大部分Web服务器,如Apache,都使用多线程的方式响应多用户请求,即一个线程服务一个用户请求。这种模式其中一个好处是,当某个请求的线程上抛出的异常没被捕获,只会影响当前这个线程,不会影响其他请求。
由于Node执行在单线程上,一旦线程上抛的异常没有被捕获,就会引起整个进程的崩溃。所以对Node服务的异常处理、保证进程的稳定性非常重要。
再好的程序员也不敢保证自己的代码不出现异常,除了尽可能捕获可能出现的异常,我们还需要通过一些规范减少异常发生,通过单元测试辅助我们验证代码,通过一些工具保证服务的稳定性。下面我从这几个方面探讨如何保证Node的稳定性。
提升稳定性最直接的方式就是尽可能的捕捉异常,Node提供3种方式。
在大多数语言中,try/catch是捕获异常的好手,能确保我们的代码不进入不可控流程。但是由于Node回调/异步的特性,我们无法通过try/catch来捕捉所有的异常,看下面的示例:
try {
process.nextTick(function () {
throw new Error("error");
});
} catch (err) {
//can not catch it
console.log(err);
}
try {
setTimeout(function(){
throw new Error("error");
},1)
} catch (err) {
//can not catch it
console.log(err);
}
上面的代码没有像预期的那样帮我们捕获异常,后果就是这个未被捕获的异常导致整个Node进程crash,所以Node中try/catch的方式不是那么管用。
如果有一种方法能帮我们全局捕获异常,Node服务就不会轻易挂掉了。Node确实提供了这种方式,不过却不能完全满足我们的需求。
当一个异常未被捕获,冒泡回归到事件循环中就会触发uncaughtException事件。
process.on('uncaughtException', function(err) {
console.error('Error caught in uncaughtException event:', err);
});
try {
setTimeout(function(){
throw new Error("error");
},1)
} catch (err) {
//can not catch it
console.log(err);
}
只要给uncaughtException配置了回调,Node进程不会异常退出,但异常发生的上下文已经丢失,我们无法给出友好的返回,比如告诉用户哪里出问题了。而且由于uncaughtException事件发生后,会丢失当前环境的堆栈,可能导致Node不能正常进行内存回收,从而导致内存泄露。所以,uncaughtException的正确使用姿势是,当uncaughtException触发,记录error日志,然后结束Node进程,我们通过日志监控,报警及时解决异常。
process.on('uncaughtException', function(err) {
// 记录日志
logger(err);
// 结束进程
process.exit(1);
});
为了弥补try/catch和uncaughtException的不足,在node v0.8+版本的时候,发布了一个模块domain
,这个模块能捕捉异步回调中出现的异常。
看下面的示例:
var d = domain.create();
process.on('uncaughtException', function(err) {
console.error(err);
});
d.on('error', function(err) {
console.error('Error caught by domain:', err);
});
d.run(function() {
process.nextTick(function() {
throw new Error("test domain");
});
});
运行代码我们会发现,异常会被domain捕获到,uncaughtException不会被触发。虽然我们对domain模块寄予厚望,不过目前domain模块的评级为“Unstable”,因为存在不少性能以及稳定性问题。
关于domain的详细介绍,可以看看以下几篇文章:
我们当然无法阻止异常的发生,这里说的阻止异常发生,是希望大家能养成良好的编码习惯,严谨的思维逻辑,来尽可能减少代码抛出未捕获异常。
fs.readFile('/t.txt', function (err, data) {
if (err) throw err;
console.log(data);
});
// 不推荐的做法
function fun(options,callback){
if(!options{
throw new Error("..")
}
}
// 推荐的做法
function fun(options,callback){
if(!options){
callback(err,null)
}
}
function doSth(cb){
if(typeof cb === 'function'){
cb();
}
}
var obj;
try{
obj = JSON.parse('')
}catch(e){
obj = {};
}
// 不推荐的做法
app.get('/item.html', function (req, res, next) {
if(!query["id"]){
throw new Error('no item id');
}
});
// 推荐的做法
app.get('/item.html', function (req, res, next) {
if(!query["id"]){
next();
}
});
单元测试的重要性想必所有人都清楚,JS代码跑在浏览器端的时候我们未必会做,因为异常通常只会影响部分人使用的部分功能,不足以引起很多人的重视。JS代码跑在服务端情况完全不一样了,一旦出现异常,影响的是所有的用户,所以单元测试就显得非常重要。
至于如何在NodeJS中写单元测试,可以看看两位大神的分享:
还是那句说,谁也不敢保证自己的代码不出现异常,因为有运行环境,网络环境等各种不稳定因素,所以建立健全的排查和跟踪机制就显得很重要,而日志就是实现这种机制的关键。
阿里线上环境已经有完善的日志监控体现,我们要做的就是去学会如何使用他。
ali-logger:http://search.npm.taobao.net/package/ali-logger
cluster模块用于创建共享端口的多进程模式,这种模式使多个进程间共享一个监听状态的socket,并由系统将accept的connection分配给不同的子进程。
文档上有一个简单的示例:
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
利用cluster
,我们可以根据CUP的数量创建多个worker进程,用户的请求会被分配到不同的进程上,如果某个进程出现异常,可以直接将这个进程crash掉,而不会影响其他进程。
关于cluster
实现原理的介绍文章非常多,想深入了解的可以自行搜索一下。
数据产品中使用graceful + recluster两个模块实现多进程和服务器稳定性的工作,分享一下使用方法:
app.js
var app = require('../app');
var graceful = require('graceful');
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
graceful({
server: server,
killTimeout: 30000,
error:function(e){
logger.error(e);
}
});
server.js
var recluster = require('recluster'),
path = require('path');
var cluster = recluster(path.join(__dirname, 'app.js'));
cluster.run();
process.on('SIGUSR2', function() {
console.log('Got SIGUSR2, reloading cluster...');
cluster.reload();
});
console.log("spawned cluster, kill -s SIGUSR2", process.pid, "to reload");
开发环境,直接通过app启动:
$ node app.js
生产环境, 启动多个 worker:
$ node server.js
如果你觉得graceful + recluster的方式太复杂,那么pm2肯定是你最理想的选择。
pm2非常强大,生产环境使用pm2启动你的Node服务是个不错的选择,他能自动利用你的多核cup,完善的监控,日志记录等等..
pm2使用非常简单:
$ npm install pm2@latest -g
$ pm2 start app.js
$ pm2 list
如果你想更多的了解pm2,可以直接看pm2的文档:https://github.com/Unitech/pm2
不过正是由于pm2功能太过强大,我们没有选择pm2,因为他太复杂了,感觉还没有能力驾驭他,特别是万一出现问题,我们还不知道如何解决。也许我们的顾虑是多余的,不过需要一点时间去了解他。
刚开始学习Node的使用,对Node确实有点小担心,因为使用别的语言做Web服务,根本不用担心因为一个错误导致整个服务crash的问题。
随着对Node的了解,我掌握了一些技巧,也打消了一些顾虑。
不过毕竟Node应用经验有限,所以欢迎大家一起探讨,积累更多宝贵的经验。
从名字就可以很容易的看出该项目的作用,rar解压缩。同时支持浏览器和Node.js。大家可以进入项目里面,了解具体用法。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.