PM2的学习记录

最近项目上线,准备上pm2,一个带有负载均衡功能的Node应用的进程管理器。抛弃forever了,哈哈。

主要特性:

  1. 内建负载均衡(使用Node cluster 集群模块)
  2. 后台运行
  3. 0秒停机重载,我理解大概意思是维护升级的时候不需要停机.
  4. 具有Ubuntu和CentOS 的启动脚本
  5. 停止不稳定的进程(避免无限循环
  6. 控制台检测
  7. 提供 HTTP API
  8. 远程控制和实时的接口API ( Nodejs 模块,允许和PM2进程管理器交互 )

下面是有用的命令:

npm install pm2 -g # 命令行安装 pm2
pm2 start app.js -i 4 #后台运行pm2,启动4个app.js
pm2 start app.js –name my-api # 命名进程
pm2 list # 显示所有进程状态
pm2 show 0 # 显示某个id的进程状态
pm2 monit # 监视所有进程
pm2 logs # 显示所有进程日志
pm2 stop all # 停止所有进程
pm2 restart all # 重启所有进程
pm2 reload all # 0秒停机重载进程 (用于 NETWORKED 进程)
pm2 stop 0 # 停止指定的进程
pm2 restart 0 # 重启指定的进程
pm2 startup # 产生 init 脚本 保持进程活着
pm2 web # 运行健壮的 computer API endpoint
pm2 delete 0 # 杀死指定的进程
pm2 delete all # 杀死全部进程

运行进程的不同方式:

Read More

理解package.json中devDependencies和dependencies的区别

用node写项目经常会用到第三方的包,阅读人家工程代码时留意到package.json里面除了我们常见的dependencies节点属性外,还看到了另外一个devDependencies,那么它们二者有什么区别呢?

dependencies 程序正常运行需要的包,是需要发布到生产环境的。devDependencies 是开发需要的包,比如一些单元测试的包之类的。其中前者依赖的项该是正常运行该包时所需要的依赖项,而后者则是开发的时候需要的依赖项,像一些进行单元测试之类的包(jslint)。

换言之,在使用 –save-dev 安装的插件它是被写入到 devDependencies对象里面去,而使用 –save 安装的插件,则被写入到 dependencies 对象里面去。

如果将包下载下来在包的根目录里运行npminstall默认会安装两种依赖,如果只是单纯的使用这个包而不需要进行一些改动测试之类的,可以使用npm install –production,只安装dependencies而不安装devDependencies。反之npm install xxx -dev

node.js作为windows服务启动

因为特殊原因,项目里node服务器需要部署在windowsServer上(怀念阿里云啊),很明显之前的forever神器就不能用了。但是回到现实中该怎么在windows上部署呢?不可能叫人家开个cmd窗口吧?怪怪的感觉,而且管理员稍不注意还容易将cmd误操作将其关闭!难不成再叫人家到目标目录,node app.js?

后来到网上搜索找到了一篇文章 将node.js程序注册为windows服务,然后按照上面的方法照做,也下载了文中提到的两个必备工具:

  1. Instrsrv.exe installs and removes system services from Windows NT.
  2. Srvany.exe allows any Windows NT application to run as a service.

最后比较遗憾的是,尽管在windows服务里面也查看到了我已经注册到的服务,但是怎么都跑不起来,重启也是一个情况。顺带说一句,它这个方案真是麻烦又难用。于是继续搜索,后来终于找到了一个工具可以解决,一个叫nssm的工具(“the Non-Sucking Service Manager”),它会监控你安装的node服务,如果node挂了,nssm会自动重启它。可以看官网深入了解。

Read More

node.js获取本机IP地址

在node.js里面获取本机IP很简单,在OS模块里面,直接调用networkInterfaces(),就可以列出你机子的所有网络接口的信息,它返回的是一个数组,如官网列出的信息:

1
2
3
4
5
6
7
8
9
10
11
{ lo0: 
[ { address: '::1', family: 'IPv6', internal: true },
{ address: 'fe80::1', family: 'IPv6', internal: true },
{ address: '127.0.0.1', family: 'IPv4', internal: true } ],
en1:
[ { address: 'fe80::cabc:c8ff:feef:f996', family: 'IPv6',
internal: false },
{ address: '10.0.1.123', family: 'IPv4', internal: false } ],
vmnet1: [ { address: '10.99.99.254', family: 'IPv4', internal: false } ],
vmnet8: [ { address: '10.88.88.1', family: 'IPv4', internal: false } ],
ppp0: [ { address: '10.2.0.231', family: 'IPv4', internal: false } ] }

据此,我们可以根据实际需要取到相应的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

function getIPAdress(){

var interfaces = require('os').networkInterfaces();

for(var devName in interfaces){

var iface = interfaces[devName];
for(var i=0;i<iface.length;i++){
var alias = iface[i];
if(alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal){
return alias.address;
}
}
}
}

Read More