Node.JS
在生产环境下安装配置使用Node.JS
在生产环境下运行Node应用,你需要保持稳定 高性能和安全,并且是可维护的,这篇文章列举了Node.js在生产环境中需要的库包和注意事项。
这篇文章需要你熟悉了解流程process是什么, upstart/systemd/init是什么和process signals. 包括项目配置和脚本等源码项目在https://github.com/dickeyxxx/node-sample.使用Digital Ocean 和 Fedora.
案例的生产环境是三个服务器,一个是负载平衡器(lb)和两个应用服务器 (app1 和 app2). 负载平衡器会进行健康检查,在两个服务器之间进行负载平衡,应用服务器综合使用systemd 和 node cluster进行负载平衡,在多个Node流程之间路由负载,部署将是可通过开发者笔记本实现一行命令方式部署,运行是可失败恢复的零当机时间。
systemd提供超过新贵一些显著的优势,包括先进的,集中式日志记录支持,配置更简单,速度快和更多的功能。案例使用Fedora.
下面是在 Fedora上安装步骤:
1.安装Node.js:
yum update -y
yum install -y git nodejs npm
npm install -g n
n stable
2.创建web用户
# useradd -mrU web
3.加入应用
- 为应用创建目录: # mkdir /var/www
- 设置拥有者给web: # chown web /var/www
- 设置群 web: # chgrp web /var/www
- 进入: # cd /var/www/
- 以web用户登录: $ su web
- Clone下载hello world应用: $ git clone https://github.com/dickeyxxx/node-hello-world,源码内容如下:
var http = require('http');
var PORT = process.env.PORT || 3000;
http.createServer(function (req, res) {
console.log('%d request received', process.pid);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello world!\n');
}).listen(PORT);
console.log('%d listening on %d', process.pid, PORT); - 运行应用:$ node app.js.
- 你可以通过浏览器访问IP得到hello world输出
- 打开防火墙:
# iptables -F
firewall-cmd --permanent --zone=public --add-port=3000/tcp
应用运行在3000端口,我们负载平衡器是80端口
systemd
现在我们已经一个运行的应用,使用systemd 确保我们应用在崩溃时能再次运行。systemd 脚本:
[Service]
WorkingDirectory=/var/www/node-hello-world
ExecStart=/usr/bin/node app.js
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=node-hello-world
User=web
Group=web
Environment='NODE_ENV=production'
[Install]
WantedBy=multi-user.target
- 在超级用户root下复制该文件到 /etc/systemd/system/node-sample.service
- 激活: # systemctl enable node-sample
- 开启: # systemctl start node-sample
- 查看状态: # systemctl status node-sample
- 观看日志: # journalctl -u node-sample
你可以杀死Node流程的pid,会发现它又启动了。
集群流程
现在我们有一个流程Node运行,我们需要使用node cluster将负载平衡到多个流程上,这里是实现零当机的脚本,只要在运行app.js后,运行:$ node boot.js
这个脚本运行应用的两个实例,如果一个死了彼此会重新启动,通过发送SIGHUP可实现零当机重新启动.可以通过$ kill -hup [pid].杀死看看。
为了启动集群,需要更新systemd配置,。加入ExecReload=/bin/kill -HUP $MAINPID 属性到你的systemd配置, 你能运行# systemctl reload node-sample 实现零当机重新启动。这里是Node cluster systemd 配置:
[Service]
WorkingDirectory=/var/www
ExecStart=/usr/bin/node boot.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=node-sample
User=web
Group=web
Environment='NODE_ENV=production'
[Install]
WantedBy=multi-user.target
负载平衡
在生产环境下,你至少需要两个服务器,以防止一个当机,负载平衡器能实现健康检查,发现有问题的服务器会不再将请求发送给它。
第一步设置另外Node.js 应用服务器,如同之前上面步骤。
安装平衡器:
安装haproxy: # yum install haproxy
改变/etc/haproxy/haproxy.cfg 为下面配置,用你的IP替代。
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
frontend main *:80
stats enable
stats uri /haproxy?stats
stats auth myusername:mypass
default_backend app
backend app
balance roundrobin
server app1 107.170.145.120:3000 check
server app2 192.241.205.146:3000 check
重启haproxy: systemctl restart haproxy
你会看到应用运行在80端口,你也可以通过/haproxy?stats 查看状态。设置 HAProxy更多信息见 this guide ,或 official docs.
使用Ansible部署代码
对于一台服务器我们可以使用如下步骤:
- SSH登录 app1
- cd /var/www/node-hello-world
- git pull 最新代码
- systemctl 重新加载 node-sample 启动应用
如果有多台服务器,就很费力,使用Ansible 可以直接从开发电脑上发布所有服务器。下面是我们部署代码的配置:
- hosts: app
tasks:
- name: update repo
git: repo=https://github.com/dickeyxxx/node-hello-world version=master dest=/var/www/node-hello-world
sudo: yes
sudo_user: web
notify:
- reload node-sample
handlers:
- name: reload node-sample
service: name=node-sample state=reloaded
[app]
192.241.205.146
107.170.233.117
在你开发电脑上运行:(确保安装了Ansible)
ansible-playbook -i production deploy.yml
使用下面配置可以让Ansible为我们实现自动准备provision :
---
- hosts: app
tasks:
- name: Install yum packages
yum: name={{item}} state=latest
with_items:
- git
- vim
- nodejs
- npm
- name: install n (node version installer/switcher)
npm: name=n state=present global=yes
- name: install the latest stable version of node
shell: n stable
- name: Create web user
user: name=web
- name: Create project folder
file: path=/var/www group=web owner=web mode=755 state=directory
- name: Add systemd conf
template: src=systemd.service.j2 dest=/etc/systemd/system/node-sample.service
notify:
- enable node-sample
handlers:
- name: enable node-sample
shell: systemctl enable node-sample
[Service]
WorkingDirectory={{project_root}}
ExecStart=/usr/bin/node boot.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier={{project_name}}
User=web
Group=web
Environment='NODE_ENV=production'
[Install]
WantedBy=multi-user.target
运行ansible-playbook -i [inventory file] app.yml
这里是适合 负载平衡器的配置.
这里是我们上面所有步骤的GitHub案例,它更新inventory file, 运行准备工作provision 并按照要求部署构建整个应用。